"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useFormFields = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const useFormFields = ({ initialFields, onChange }) => {
    const [formFields, setFormFields] = React.useState(initialFields);
    const [nextId, setNextId] = React.useState(initialFields.length + 1);
    const generateId = React.useCallback(() => {
        const id = `field_id_${nextId}`;
        setNextId((prev) => prev + 1);
        return id;
    }, [nextId]);
    const generateName = React.useCallback(() => {
        const name = `field_${nextId}`;
        return name;
    }, [nextId]);
    const updateFormFields = React.useCallback((fields) => {
        setFormFields(fields);
        onChange?.(fields);
    }, [onChange]);
    const createField = React.useCallback((type, name = '') => {
        const fieldName = name || generateName();
        const fieldId = generateId();
        let newField;
        switch (type) {
            case 'text':
                newField = {
                    type: 'text',
                    name: fieldName,
                    title: 'Text Input',
                    id: fieldId,
                };
                break;
            case 'number':
                newField = {
                    type: 'number',
                    name: fieldName,
                    title: 'Number Input',
                    id: fieldId,
                };
                break;
            case 'boolean':
                newField = {
                    type: 'boolean',
                    name: fieldName,
                    title: 'Boolean Input',
                    id: fieldId,
                };
                break;
            case 'textarea':
                newField = {
                    type: 'textarea',
                    name: fieldName,
                    title: 'Textarea Input',
                    id: fieldId,
                };
                break;
            case 'select':
                newField = {
                    type: 'select',
                    name: fieldName,
                    title: 'Select Input',
                    view: 'select',
                    mode: 'single',
                    enum: [
                        { content: 'Option 1', value: 'option1' },
                        { content: 'Option 2', value: 'option2' },
                    ],
                    id: fieldId,
                };
                break;
            case 'object':
                newField = {
                    type: 'object',
                    name: fieldName,
                    title: 'Object Input',
                    properties: [
                        {
                            type: 'text',
                            name: 'property1',
                            title: 'Property 1',
                            id: generateId(),
                        },
                    ],
                    id: fieldId,
                };
                break;
            case 'array':
                newField = {
                    type: 'array',
                    name: fieldName,
                    title: 'Array Input',
                    buttonText: 'Add Item',
                    arrayType: 'text',
                    id: fieldId,
                };
                break;
            case 'oneOf':
                newField = {
                    type: 'oneOf',
                    name: fieldName,
                    title: 'OneOf Input',
                    options: [
                        {
                            title: 'Option A',
                            value: 'optionA',
                            properties: [
                                {
                                    type: 'text',
                                    name: 'textField',
                                    title: 'Text Field',
                                    id: generateId(),
                                },
                            ],
                        },
                        {
                            title: 'Option B',
                            value: 'optionB',
                            properties: [
                                {
                                    type: 'number',
                                    name: 'numberField',
                                    title: 'Number Field',
                                    id: generateId(),
                                },
                            ],
                        },
                    ],
                    id: fieldId,
                };
                break;
            case 'anyOf':
                newField = {
                    type: 'anyOf',
                    name: fieldName,
                    title: 'AnyOf Input',
                    options: [
                        {
                            title: 'Option A',
                            value: 'optionA',
                            properties: [
                                {
                                    type: 'text',
                                    name: 'textField',
                                    title: 'Text Field',
                                    id: generateId(),
                                },
                            ],
                        },
                        {
                            title: 'Option B',
                            value: 'optionB',
                            properties: [
                                {
                                    type: 'boolean',
                                    name: 'booleanField',
                                    title: 'Boolean Field',
                                    id: generateId(),
                                },
                            ],
                        },
                    ],
                    id: fieldId,
                };
                break;
            default:
                return createField('text', fieldName);
        }
        return newField;
    }, [generateId, generateName]);
    const updateFieldById = React.useCallback((fields, fieldId, updates) => {
        return fields.map((field) => {
            if (field.id === fieldId) {
                return { ...field, ...updates };
            }
            if (field.type === 'object' && field.properties) {
                const objectField = field;
                return {
                    ...field,
                    properties: updateFieldById(objectField.properties, fieldId, updates),
                };
            }
            if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                field.options) {
                const optionsField = field;
                return {
                    ...field,
                    options: optionsField.options.map((option) => ({
                        ...option,
                        properties: updateFieldById(option.properties, fieldId, updates),
                    })),
                };
            }
            if (field.type === 'array' && field.arrayType === 'object') {
                const arrayField = field;
                return {
                    ...field,
                    properties: updateFieldById(arrayField.properties, fieldId, updates),
                };
            }
            return field;
        });
    }, []);
    const addField = React.useCallback((type) => {
        const newField = createField(type);
        updateFormFields([...formFields, newField]);
    }, [createField, formFields, updateFormFields]);
    const removeField = React.useCallback((fieldId) => {
        updateFormFields(formFields.filter((field) => field.id !== fieldId));
    }, [formFields, updateFormFields]);
    const updateField = React.useCallback((fieldId, updates) => {
        updateFormFields(updateFieldById(formFields, fieldId, updates));
    }, [formFields, updateFieldById, updateFormFields]);
    const addPropertyToObjectById = React.useCallback((fields, objectId, type = 'text') => {
        return fields.map((field) => {
            if (field.id === objectId && field.type === 'object') {
                const objectField = field;
                const propertyName = `property${(objectField.properties?.length || 0) + 1}`;
                const newProperty = createField(type, propertyName);
                return {
                    ...field,
                    properties: [...(objectField.properties || []), newProperty],
                };
            }
            if (field.type === 'object' && field.properties) {
                const objectField = field;
                return {
                    ...field,
                    properties: addPropertyToObjectById(objectField.properties, objectId, type),
                };
            }
            if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                field.options) {
                const optionsField = field;
                return {
                    ...field,
                    options: optionsField.options.map((option) => ({
                        ...option,
                        properties: addPropertyToObjectById(option.properties, objectId, type),
                    })),
                };
            }
            if (field.type === 'array' && field.arrayType === 'object') {
                const arrayField = field;
                if (field.id === objectId) {
                    const propertyName = `property${(arrayField.properties?.length || 0) + 1}`;
                    const newProperty = createField(type, propertyName);
                    return {
                        ...field,
                        properties: [...(arrayField.properties || []), newProperty],
                    };
                }
                if (arrayField.properties && arrayField.properties.length > 0) {
                    return {
                        ...field,
                        properties: addPropertyToObjectById(arrayField.properties, objectId, type),
                    };
                }
            }
            return field;
        });
    }, [createField]);
    const addObjectProperty = React.useCallback((objectId, type = 'text') => {
        updateFormFields(addPropertyToObjectById(formFields, objectId, type));
    }, [formFields, addPropertyToObjectById, updateFormFields]);
    const addOptionProperty = React.useCallback((fieldId, optionIndex, type = 'text') => {
        const addPropertyToOptionRecursive = (fields, targetFieldId, targetOptionIndex) => {
            return fields.map((field) => {
                if (field.id === targetFieldId &&
                    (field.type === 'oneOf' || field.type === 'anyOf')) {
                    const updatedField = JSON.parse(JSON.stringify(field));
                    const options = updatedField.options;
                    if (options &&
                        Array.isArray(options) &&
                        targetOptionIndex >= 0 &&
                        targetOptionIndex < options.length &&
                        options[targetOptionIndex].properties) {
                        const propertyName = `property${options[targetOptionIndex].properties.length + 1}`;
                        const newProperty = createField(type, propertyName);
                        options[targetOptionIndex].properties.push(newProperty);
                    }
                    return updatedField;
                }
                if (field.type === 'object' && field.properties) {
                    const objectField = field;
                    return {
                        ...field,
                        properties: addPropertyToOptionRecursive(objectField.properties, targetFieldId, targetOptionIndex),
                    };
                }
                if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                    field.options) {
                    const optionsField = field;
                    return {
                        ...field,
                        options: optionsField.options.map((option) => ({
                            ...option,
                            properties: addPropertyToOptionRecursive(option.properties, targetFieldId, targetOptionIndex),
                        })),
                    };
                }
                if (field.type === 'array' &&
                    field.arrayType === 'object' &&
                    field.properties) {
                    const arrayField = field;
                    return {
                        ...field,
                        properties: addPropertyToOptionRecursive(arrayField.properties, targetFieldId, targetOptionIndex),
                    };
                }
                return field;
            });
        };
        setFormFields((prev) => addPropertyToOptionRecursive(prev, fieldId, optionIndex));
    }, [createField]);
    const removeObjectProperty = React.useCallback((fieldId, propertyIndex) => {
        updateFormFields(formFields.map((field) => {
            if (field.id !== fieldId)
                return field;
            const updatedField = JSON.parse(JSON.stringify(field));
            const objectInput = updatedField;
            objectInput.properties.splice(propertyIndex, 1);
            return updatedField;
        }));
    }, [formFields, updateFormFields]);
    const removeOptionProperty = React.useCallback((fieldId, optionIndex, propertyIndex) => {
        const removePropertyFromOptionRecursive = (fields, targetFieldId, targetOptionIndex, targetPropertyIndex) => {
            return fields.map((field) => {
                if (field.id === targetFieldId &&
                    (field.type === 'oneOf' || field.type === 'anyOf')) {
                    const updatedField = JSON.parse(JSON.stringify(field));
                    const options = updatedField.options;
                    if (options &&
                        Array.isArray(options) &&
                        targetOptionIndex >= 0 &&
                        targetOptionIndex < options.length &&
                        options[targetOptionIndex].properties &&
                        targetPropertyIndex >= 0 &&
                        targetPropertyIndex < options[targetOptionIndex].properties.length) {
                        options[targetOptionIndex].properties.splice(targetPropertyIndex, 1);
                    }
                    return updatedField;
                }
                if (field.type === 'object' && field.properties) {
                    const objectField = field;
                    return {
                        ...field,
                        properties: removePropertyFromOptionRecursive(objectField.properties, targetFieldId, targetOptionIndex, targetPropertyIndex),
                    };
                }
                if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                    field.options) {
                    const optionsField = field;
                    return {
                        ...field,
                        options: optionsField.options.map((option) => ({
                            ...option,
                            properties: removePropertyFromOptionRecursive(option.properties, targetFieldId, targetOptionIndex, targetPropertyIndex),
                        })),
                    };
                }
                if (field.type === 'array' &&
                    field.arrayType === 'object' &&
                    field.properties) {
                    const arrayField = field;
                    return {
                        ...field,
                        properties: removePropertyFromOptionRecursive(arrayField.properties, targetFieldId, targetOptionIndex, targetPropertyIndex),
                    };
                }
                return field;
            });
        };
        setFormFields((prev) => removePropertyFromOptionRecursive(prev, fieldId, optionIndex, propertyIndex));
    }, []);
    const updateObjectProperty = React.useCallback((fieldId, propertyIndex, updates) => {
        updateFormFields(formFields.map((field) => {
            if (field.id !== fieldId)
                return field;
            const updatedField = JSON.parse(JSON.stringify(field));
            const objectInput = updatedField;
            objectInput.properties[propertyIndex] = {
                ...objectInput.properties[propertyIndex],
                ...updates,
            };
            return updatedField;
        }));
    }, [formFields, updateFormFields]);
    const updateOptionProperty = React.useCallback((fieldId, optionIndex, propertyIndex, updates) => {
        const updatePropertyInOptionRecursive = (fields, targetFieldId, targetOptionIndex, targetPropertyIndex, propertyUpdates) => {
            return fields.map((field) => {
                if (field.id === targetFieldId &&
                    (field.type === 'oneOf' || field.type === 'anyOf')) {
                    const updatedField = JSON.parse(JSON.stringify(field));
                    const options = updatedField.options;
                    if (options &&
                        Array.isArray(options) &&
                        targetOptionIndex >= 0 &&
                        targetOptionIndex < options.length &&
                        options[targetOptionIndex].properties &&
                        targetPropertyIndex >= 0 &&
                        targetPropertyIndex < options[targetOptionIndex].properties.length) {
                        options[targetOptionIndex].properties[targetPropertyIndex] = {
                            ...options[targetOptionIndex].properties[targetPropertyIndex],
                            ...propertyUpdates,
                        };
                    }
                    return updatedField;
                }
                if (field.type === 'object' && field.properties) {
                    const objectField = field;
                    return {
                        ...field,
                        properties: updatePropertyInOptionRecursive(objectField.properties, targetFieldId, targetOptionIndex, targetPropertyIndex, propertyUpdates),
                    };
                }
                if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                    field.options) {
                    const optionsField = field;
                    return {
                        ...field,
                        options: optionsField.options.map((option) => ({
                            ...option,
                            properties: updatePropertyInOptionRecursive(option.properties, targetFieldId, targetOptionIndex, targetPropertyIndex, propertyUpdates),
                        })),
                    };
                }
                if (field.type === 'array' &&
                    field.arrayType === 'object' &&
                    field.properties) {
                    const arrayField = field;
                    return {
                        ...field,
                        properties: updatePropertyInOptionRecursive(arrayField.properties, targetFieldId, targetOptionIndex, targetPropertyIndex, propertyUpdates),
                    };
                }
                return field;
            });
        };
        setFormFields((prev) => updatePropertyInOptionRecursive(prev, fieldId, optionIndex, propertyIndex, updates));
    }, []);
    const addOption = React.useCallback((fieldId) => {
        const addOptionRecursive = (fields, targetFieldId) => {
            return fields.map((field) => {
                if (field.id === targetFieldId &&
                    (field.type === 'oneOf' || field.type === 'anyOf')) {
                    const updatedField = JSON.parse(JSON.stringify(field));
                    const options = updatedField.options;
                    if (options && Array.isArray(options)) {
                        const optionLetter = String.fromCharCode(65 + options.length);
                        const newOption = {
                            title: `Option ${optionLetter}`,
                            value: `option${optionLetter.toLowerCase()}`,
                            properties: [
                                {
                                    type: 'text',
                                    name: 'textField',
                                    title: 'Text Field',
                                    id: generateId(),
                                },
                            ],
                        };
                        options.push(newOption);
                    }
                    return updatedField;
                }
                if (field.type === 'object' && field.properties) {
                    const objectField = field;
                    return {
                        ...field,
                        properties: addOptionRecursive(objectField.properties, targetFieldId),
                    };
                }
                if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                    field.options) {
                    const optionsField = field;
                    return {
                        ...field,
                        options: optionsField.options.map((option) => ({
                            ...option,
                            properties: addOptionRecursive(option.properties, targetFieldId),
                        })),
                    };
                }
                if (field.type === 'array' &&
                    field.arrayType === 'object' &&
                    field.properties) {
                    const arrayField = field;
                    return {
                        ...field,
                        properties: addOptionRecursive(arrayField.properties, targetFieldId),
                    };
                }
                return field;
            });
        };
        setFormFields((prev) => addOptionRecursive(prev, fieldId));
    }, [generateId]);
    const removeOption = React.useCallback((fieldId, optionIndex) => {
        const removeOptionRecursive = (fields, targetFieldId, targetOptionIndex) => {
            return fields.map((field) => {
                if (field.id === targetFieldId &&
                    (field.type === 'oneOf' || field.type === 'anyOf')) {
                    const updatedField = JSON.parse(JSON.stringify(field));
                    const options = updatedField.options;
                    if (options &&
                        Array.isArray(options) &&
                        targetOptionIndex >= 0 &&
                        targetOptionIndex < options.length) {
                        if (options.length > 1) {
                            options.splice(targetOptionIndex, 1);
                        }
                    }
                    return updatedField;
                }
                if (field.type === 'object' && field.properties) {
                    const objectField = field;
                    return {
                        ...field,
                        properties: removeOptionRecursive(objectField.properties, targetFieldId, targetOptionIndex),
                    };
                }
                if ((field.type === 'oneOf' || field.type === 'anyOf') &&
                    field.options) {
                    const optionsField = field;
                    return {
                        ...field,
                        options: optionsField.options.map((option) => ({
                            ...option,
                            properties: removeOptionRecursive(option.properties, targetFieldId, targetOptionIndex),
                        })),
                    };
                }
                if (field.type === 'array' &&
                    field.arrayType === 'object' &&
                    field.properties) {
                    const arrayField = field;
                    return {
                        ...field,
                        properties: removeOptionRecursive(arrayField.properties, targetFieldId, targetOptionIndex),
                    };
                }
                return field;
            });
        };
        updateFormFields(removeOptionRecursive(formFields, fieldId, optionIndex));
    }, [formFields, updateFormFields]);
    const resetForm = React.useCallback(() => {
        updateFormFields([]);
    }, [updateFormFields]);
    return {
        formFields,
        createField,
        addField,
        removeField,
        updateField,
        addObjectProperty,
        addOptionProperty,
        removeObjectProperty,
        removeOptionProperty,
        updateObjectProperty,
        updateOptionProperty,
        addOption,
        removeOption,
        resetForm,
    };
};
exports.useFormFields = useFormFields;
//# sourceMappingURL=useFormFields.js.map
