import { deepClone } from '@takeshape/util';
import { getRefOrItemsRef, refItemToNamespacedShapeName } from "../refs.js";
import { createSchemaPropertyAccessor } from "../schema-util.js";
/**
 * If there any non-normal (nested) forms in the schema, create forms for referenced shapes.
 * The original forms are left intact.
 */
export function normalizeForms(projectSchema) {
    const normalizedForms = {};
    const { forms = {} } = projectSchema;
    const storeSourceForm = (shapeName, formConfig, propName) => {
        // Leave original forms intact for backwards compatibility
        if (!forms[shapeName]) {
            normalizedForms[shapeName] ||= { default: deepClone(formConfig) };
            // Remove prop now that it has been normalized
            delete normalizedForms[shapeName].default.properties[propName];
        }
    };
    const normalizeNested = (shapeName, formConfig) => {
        const shape = projectSchema.shapes[shapeName];
        if (!shape || !formConfig.properties) {
            return;
        }
        const propertyAccessor = createSchemaPropertyAccessor(projectSchema, shape);
        for (const propName of Object.keys(formConfig.properties)) {
            const propConfig = formConfig.properties[propName];
            const propSchema = propertyAccessor.getValue(propName);
            if (propSchema) {
                const ref = getRefOrItemsRef(projectSchema, propSchema);
                if (ref && propConfig.properties) {
                    const nestedShapeName = refItemToNamespacedShapeName(projectSchema, ref);
                    normalizedForms[nestedShapeName] = { default: deepClone(propConfig) };
                    storeSourceForm(shapeName, formConfig, propName);
                    normalizeNested(nestedShapeName, propConfig);
                }
            }
        }
    };
    if (forms) {
        for (const shapeName of Object.keys(forms)) {
            normalizeNested(shapeName, forms[shapeName].default);
            // copy forms with no changes
            normalizedForms[shapeName] ||= forms[shapeName];
        }
    }
    return normalizedForms;
}
const cache = new WeakMap();
/**
 * Find the form config for a given shape name and the form key.
 */
export function findShapeFormConfig(projectSchema, shapeName, formName) {
    if (!projectSchema.forms) {
        return;
    }
    let normalizedForms = cache.get(projectSchema);
    if (!normalizedForms) {
        normalizedForms = normalizeForms(projectSchema);
        cache.set(projectSchema, normalizedForms);
    }
    return normalizedForms[shapeName]?.[formName];
}
