import { visit } from '@takeshape/util';
import pickBy from 'lodash/pickBy.js';
import { getContentTransform } from "./content-schema-transform.js";
import { isObjectSchema } from "./types/index.js";
import { createUnwrapTransform, createWrapTransform, isUnionSchema } from "./unions.js";
function createPropertiesPredicate(propertyNames) {
    const byShape = new Map();
    for (const name of propertyNames) {
        const [shapeName, propName] = name.split('.');
        const blacklist = byShape.get(shapeName);
        if (!blacklist) {
            byShape.set(shapeName, new Set([propName]));
        }
        else {
            blacklist.add(propName);
        }
    }
    return (shapeName, name) => {
        const blacklist = byShape.get(byShape.has(shapeName) ? shapeName : '*');
        return Boolean(blacklist?.has(name));
    };
}
export function removePropertiesTransform(propertyNames) {
    const isBlacklisted = createPropertiesPredicate(propertyNames);
    return (projectSchema) => {
        visit(projectSchema, ['schema'], (value, path) => {
            if (path.length === 3 && path[0] === 'shapes' && path[2] === 'schema') {
                const shapeSchema = value;
                if (isObjectSchema(shapeSchema)) {
                    const { properties, required } = shapeSchema;
                    shapeSchema.properties = pickBy(properties, (_, name) => !isBlacklisted(path[1], name));
                    if (required) {
                        shapeSchema.required = required.filter((name) => !isBlacklisted(path[1], name));
                    }
                }
            }
        });
        return projectSchema;
    };
}
export function toName(name) {
    return name;
}
export function transformOneOf(process) {
    return (projectSchema, schema, obj) => {
        const transform = getContentTransform({
            sourceKeyTransform: toName,
            keyTransform: toName,
            passThrough: true,
            projectSchema,
            transforms: {
                '*': [
                    {
                        filter: isUnionSchema,
                        process: process(projectSchema)
                    }
                ]
            }
        });
        return transform(schema, obj);
    };
}
/**
 * Unwrap oneOf objects in "GraphQL oneOf" style wrapper objects
 * See https://github.com/graphql/graphql-spec/pull/825 for more on "GraphQL oneOf"
 * Opposite of `wrapOneOfObjects`
 */
export const unwrapOneOfObjects = transformOneOf(createUnwrapTransform);
/**
 * Wrap oneOf objects in "GraphQL oneOf" style wrapper objects
 * See https://github.com/graphql/graphql-spec/pull/825 for more on "GraphQL oneOf"
 * Opposite of `unwrapOneOfObjects`
 */
export const wrapOneOfObjects = transformOneOf(createWrapTransform);
