"use strict";
var __webpack_require__ = {};
(()=>{
    __webpack_require__.d = function(exports1, definition) {
        for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
            enumerable: true,
            get: definition[key]
        });
    };
})();
(()=>{
    __webpack_require__.o = function(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    };
})();
(()=>{
    __webpack_require__.r = function(exports1) {
        if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
            value: 'Module'
        });
        Object.defineProperty(exports1, '__esModule', {
            value: true
        });
    };
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
    useDesignable: ()=>useDesignable,
    createDesignable: ()=>createDesignable,
    useFindComponent: ()=>useFindComponent,
    Designable: ()=>Designable,
    splitWrapSchema: ()=>splitWrapSchema
});
const jsx_runtime_namespaceObject = require("react/jsx-runtime");
const external_react_namespaceObject = require("react");
const schema_namespaceObject = require("@tachybase/schema");
const external_lodash_namespaceObject = require("lodash");
const external_react_i18next_namespaceObject = require("react-i18next");
const index_js_namespaceObject = require("../../api-client/index.js");
const external_context_js_namespaceObject = require("../context.js");
function _define_property(obj, key, value) {
    if (key in obj) Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
    });
    else obj[key] = value;
    return obj;
}
function createDesignable(options) {
    return new Designable(options);
}
const generateUid = (s)=>{
    if (!s['x-uid']) s['x-uid'] = (0, schema_namespaceObject.uid)();
    Object.keys(s.properties || {}).forEach((key)=>{
        generateUid(s.properties[key]);
    });
};
const defaultWrap = (s)=>s;
const matchSchema = (source, target)=>{
    if (!source || !target) return;
    for(const key in target)if (Object.prototype.hasOwnProperty.call(target, key)) {
        const value = target[key];
        if (value !== (null == source ? void 0 : source[key])) return false;
    }
    return true;
};
const splitWrapSchema = (wrapped, schema)=>{
    if (wrapped['x-uid'] && wrapped['x-uid'] === schema['x-uid']) return [
        null,
        wrapped.toJSON()
    ];
    const wrappedJson = wrapped.toJSON();
    const schema1 = {
        ...wrappedJson,
        properties: {}
    };
    let schema2 = null;
    const findSchema = (properties, parent)=>{
        Object.keys(properties || {}).forEach((key)=>{
            const current = properties[key];
            if (current['x-uid'] === schema['x-uid']) {
                schema2 = properties[key];
                return;
            }
            parent.properties[key] = {
                ...current,
                properties: {}
            };
            findSchema(null == current ? void 0 : current.properties, parent.properties[key]);
        });
    };
    findSchema(wrappedJson.properties, schema1);
    return [
        schema1,
        schema2
    ];
};
const translate = (v)=>v;
class Designable {
    get model() {
        return this.options.model;
    }
    get query() {
        return this.options.query;
    }
    loadAPIClientEvents() {
        const { api, t = translate } = this.options;
        if (!api) return;
        const updateColumnSize = (parent)=>{
            if (!parent) return [];
            const len = Object.values(parent.properties).length;
            const schemas = [];
            parent.mapProperties((s)=>{
                s['x-component-props'] = s['x-component-props'] || {};
                s['x-component-props']['width'] = 100 / len;
                if (s['x-uid']) schemas.push({
                    'x-uid': s['x-uid'],
                    'x-component-props': s['x-component-props']
                });
            });
            if (parent['x-uid'] && schemas.length) return schemas;
            return [];
        };
        this.on('insertAdjacent', async (param)=>{
            let { onSuccess, current, position, schema, wrap, wrapped, removed } = param;
            var _res_data;
            let schemas = [];
            if ((null == wrapped ? void 0 : wrapped['x-component']) === 'Grid.Col') schemas = schemas.concat(updateColumnSize(wrapped.parent));
            if ((null == removed ? void 0 : removed['x-component']) === 'Grid.Col') schemas = schemas.concat(updateColumnSize(removed.parent));
            this.refresh();
            if (!current['x-uid']) return;
            const res = await api.request({
                url: "/uiSchemas:insertAdjacent/".concat(current['x-uid'], "?position=").concat(position),
                method: 'post',
                data: {
                    schema,
                    wrap
                }
            });
            if (schemas.length) await api.request({
                url: "/uiSchemas:batchPatch",
                method: 'post',
                data: schemas
            });
            if (null == removed ? void 0 : removed['x-uid']) await api.request({
                url: "/uiSchemas:remove/".concat(removed['x-uid']),
                method: 'post'
            });
            null == onSuccess || onSuccess(null == res ? void 0 : null === (_res_data = res.data) || void 0 === _res_data ? void 0 : _res_data.data);
        });
        this.on('patch', async (param)=>{
            let { schema } = param;
            this.refresh();
            if (!(null == schema ? void 0 : schema['x-uid'])) return;
            await api.request({
                url: "/uiSchemas:patch",
                method: 'post',
                data: {
                    ...schema
                }
            });
        });
        this.on('batchPatch', async (param)=>{
            let { schemas } = param;
            this.refresh();
            await api.request({
                url: "/uiSchemas:batchPatch",
                method: 'post',
                data: schemas
            });
        });
        this.on('remove', async (param)=>{
            let { removed } = param;
            let schemas = [];
            if ((null == removed ? void 0 : removed['x-component']) === 'Grid.Col') schemas = updateColumnSize(removed.parent);
            this.refresh();
            if (!(null == removed ? void 0 : removed['x-uid'])) return;
            await api.request({
                url: "/uiSchemas:remove/".concat(removed['x-uid']),
                method: 'post'
            });
            if (schemas.length) await api.request({
                url: "/uiSchemas:batchPatch",
                method: 'post',
                data: schemas
            });
        });
    }
    prepareProperty(schema) {
        if (!schema.type) schema.type = 'void';
        if (!schema.name) schema.name = (0, schema_namespaceObject.uid)();
        if (!this.current['x-uid']) return;
        generateUid(schema);
    }
    on(name, listener) {
        if (!this.events[name]) this.events[name] = [];
        this.events[name].push(listener);
    }
    async emit(name) {
        for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++)args[_key - 1] = arguments[_key];
        if (!this.events[name]) return;
        const [opts, ...others] = args;
        return Promise.all(this.events[name].map((fn)=>fn.bind(this)({
                current: this.current,
                ...opts
            }, ...others)));
    }
    parentsIn(schema) {
        if (!schema) return false;
        if (!schema_namespaceObject.Schema.isSchemaInstance(schema)) return false;
        let s = this.current;
        while(null == s ? void 0 : s.parent){
            if (s.parent === schema) return true;
            s = s.parent;
        }
        return false;
    }
    refresh() {
        const { refresh } = this.options;
        return null == refresh ? void 0 : refresh();
    }
    deepMerge(schema) {
        const replaceKeys = {
            title: 'title',
            description: 'description',
            default: 'initialValue',
            readOnly: 'readOnly',
            writeOnly: 'editable',
            enum: 'dataSource',
            'x-pattern': 'pattern',
            'x-display': 'display',
            'x-validator': 'validator',
            'x-decorator': 'decorator',
            'x-component': 'component',
            'x-reactions': 'reactions',
            'x-content': 'content',
            'x-visible': 'visible',
            'x-hidden': 'hidden',
            'x-disabled': 'disabled',
            'x-editable': 'editable',
            'x-read-only': 'readOnly'
        };
        const mergeKeys = {
            'x-decorator-props': 'decoratorProps',
            'x-component-props': 'componentProps',
            'x-data': 'data'
        };
        Object.keys(schema).forEach((key)=>{
            if (replaceKeys[key]) {
                this.current[key] = schema[key];
                this.updateModel(replaceKeys[key], schema[key]);
            } else if (mergeKeys[key]) Object.keys(schema[key]).forEach((key2)=>{
                (0, external_lodash_namespaceObject.set)(this.current, [
                    key,
                    key2
                ], schema[key][key2]);
                this.updateModel([
                    mergeKeys[key],
                    key2
                ], schema[key][key2]);
            });
            else this.current[key] = schema[key];
        });
        this.emit('patch', {
            schema
        });
    }
    getSchemaAttribute(key, defaultValue) {
        return (0, external_lodash_namespaceObject.get)(this.current, key, defaultValue);
    }
    shallowMerge(schema) {
        const replaceKeys = {
            title: 'title',
            description: 'description',
            default: 'initialValue',
            readOnly: 'readOnly',
            writeOnly: 'editable',
            enum: 'dataSource',
            'x-pattern': 'pattern',
            'x-display': 'display',
            'x-validator': 'validator',
            'x-decorator': 'decorator',
            'x-component': 'component',
            'x-reactions': 'reactions',
            'x-content': 'content',
            'x-visible': 'visible',
            'x-hidden': 'hidden',
            'x-disabled': 'disabled',
            'x-editable': 'editable',
            'x-read-only': 'readOnly',
            'x-decorator-props': 'decoratorProps',
            'x-component-props': 'componentProps',
            'x-data': 'data'
        };
        Object.keys(schema).forEach((key)=>{
            this.current[key] = schema[key];
            if (replaceKeys[key]) this.updateModel(replaceKeys[key], schema[key]);
        });
        this.emit('patch', {
            schema
        });
    }
    updateModel(key, value) {
        const update = (field)=>{
            (0, external_lodash_namespaceObject.set)(field, key, value);
        };
        if (this.model) update(this.model);
        if (this.query) this.query.take(update);
    }
    insertAdjacent(position, schema) {
        let options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {};
        switch(position){
            case 'beforeBegin':
                return this.insertBeforeBegin(schema, options);
            case 'afterBegin':
                return this.insertAfterBegin(schema, options);
            case 'beforeEnd':
                return this.insertBeforeEnd(schema, options);
            case 'afterEnd':
                return this.insertAfterEnd(schema, options);
        }
    }
    recursiveRemoveIfNoChildren(schema, options) {
        if (!schema) return;
        let s = schema;
        let removed;
        const breakRemoveOn = null == options ? void 0 : options.breakRemoveOn;
        while(s){
            if ('function' == typeof breakRemoveOn) {
                if (breakRemoveOn(s)) break;
            } else if (matchSchema(s, breakRemoveOn)) break;
            const count = Object.keys(s.properties || {}).length;
            if (count > 0) break;
            if (s.parent) removed = s.parent.removeProperty(s.name);
            s = s.parent;
        }
        return removed;
    }
    remove(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        const { breakRemoveOn, removeParentsIfNoChildren } = options;
        const s = schema || this.current;
        let removed = s.parent.removeProperty(s.name);
        if (removeParentsIfNoChildren) {
            const parent = this.recursiveRemoveIfNoChildren(s.parent, {
                breakRemoveOn
            });
            if (parent) removed = parent;
        }
        return this.emit('remove', {
            removed
        });
    }
    removeWithoutEmit(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        const { breakRemoveOn, removeParentsIfNoChildren } = options;
        const s = schema || this.current;
        let removed = s.parent.removeProperty(s.name);
        if (removeParentsIfNoChildren) {
            const parent = this.recursiveRemoveIfNoChildren(s.parent, {
                breakRemoveOn
            });
            if (parent) removed = parent;
        }
        return removed;
    }
    insertBeforeBeginOrAfterEnd(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        if (!schema_namespaceObject.Schema.isSchemaInstance(this.current)) return;
        if (!schema_namespaceObject.Schema.isSchemaInstance(schema)) return;
        if (this.current.parent !== schema.parent) return;
        let fromIndex = 0;
        let toIndex = 0;
        this.current.parent.mapProperties((property, key, index)=>{
            if (this.current.name === key) toIndex = index;
            if (schema.name === key) fromIndex = index;
        });
        return fromIndex > toIndex ? this.insertBeforeBegin(schema, options) : this.insertAfterEnd(schema, options);
    }
    insertBeforeBegin(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        if (!schema_namespaceObject.Schema.isSchemaInstance(this.current)) return;
        const opts = {
            onSuccess: options.onSuccess
        };
        const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options;
        if (schema_namespaceObject.Schema.isSchemaInstance(schema)) {
            if (this.parentsIn(schema)) {
                this.emit('error', {
                    code: 'parent_is_not_allowed',
                    schema
                });
                return;
            }
            schema.parent.removeProperty(schema.name);
            if (removeParentsIfNoChildren) opts['removed'] = this.recursiveRemoveIfNoChildren(schema.parent, {
                breakRemoveOn
            });
        } else if (schema) schema = (0, external_lodash_namespaceObject.cloneDeep)(schema);
        const properties = {};
        let start = false;
        let order = 0;
        let newOrder = 0;
        this.current.parent.mapProperties((property, key)=>{
            if (key === this.current.name) {
                newOrder = order;
                start = true;
                ++order;
            }
            property['x-index'] = order;
            ++order;
            if (start) {
                properties[key] = property;
                this.current.parent.removeProperty(key);
            }
        });
        this.prepareProperty(schema);
        const wrapped = wrap(schema);
        const s = this.current.parent.addProperty(wrapped.name || (0, schema_namespaceObject.uid)(), wrapped);
        s['x-index'] = newOrder;
        s.parent = this.current.parent;
        this.current.parent.setProperties(properties);
        const [schema1, schema2] = splitWrapSchema(s, schema);
        this.emit('insertAdjacent', {
            position: 'beforeBegin',
            schema: schema2,
            wrapped,
            wrap: schema1,
            ...opts
        });
    }
    insertAfterBegin(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        if (!schema_namespaceObject.Schema.isSchemaInstance(this.current)) return;
        const opts = {
            onSuccess: options.onSuccess
        };
        const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options;
        if (schema_namespaceObject.Schema.isSchemaInstance(schema)) {
            if (this.parentsIn(schema)) {
                this.emit('error', {
                    code: 'parent_is_not_allowed',
                    schema
                });
                return;
            }
            schema.parent.removeProperty(schema.name);
            if (removeParentsIfNoChildren) opts['removed'] = this.recursiveRemoveIfNoChildren(schema.parent, {
                breakRemoveOn
            });
        } else if (schema) schema = (0, external_lodash_namespaceObject.cloneDeep)(schema);
        const properties = {};
        let order = 1;
        this.current.mapProperties((s, key)=>{
            s['x-index'] = order;
            ++order;
            properties[key] = s;
        });
        this.current.properties = {};
        this.prepareProperty(schema);
        const wrapped = wrap(schema);
        const s = this.current.addProperty(wrapped.name || (0, schema_namespaceObject.uid)(), wrapped);
        s['x-index'] = 0;
        s.parent = this.current;
        this.current.setProperties(properties);
        const [schema1, schema2] = splitWrapSchema(s, schema);
        this.emit('insertAdjacent', {
            position: 'afterBegin',
            schema: schema2,
            wrap: schema1,
            wrapped,
            ...opts
        });
    }
    insertBeforeEnd(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        if (!schema_namespaceObject.Schema.isSchemaInstance(this.current)) return;
        delete schema['x-index'];
        const opts = {
            onSuccess: options.onSuccess
        };
        const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options;
        if (schema_namespaceObject.Schema.isSchemaInstance(schema)) {
            if (this.parentsIn(schema)) {
                this.emit('error', {
                    code: 'parent_is_not_allowed',
                    schema
                });
                return;
            }
            schema.parent.removeProperty(schema.name);
            if (removeParentsIfNoChildren) opts['removed'] = this.recursiveRemoveIfNoChildren(schema.parent, {
                breakRemoveOn
            });
        } else if (schema) schema = (0, external_lodash_namespaceObject.cloneDeep)(schema);
        this.prepareProperty(schema);
        const wrapped = wrap(schema);
        const s = this.current.addProperty(wrapped.name || (0, schema_namespaceObject.uid)(), wrapped);
        s.parent = this.current;
        const [schema1, schema2] = splitWrapSchema(s, schema);
        return this.emit('insertAdjacent', {
            position: 'beforeEnd',
            schema: schema2,
            wrap: schema1,
            wrapped,
            ...opts
        });
    }
    insertAfterEnd(schema) {
        let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
        if (!schema_namespaceObject.Schema.isSchemaInstance(this.current)) return;
        const opts = {
            onSuccess: null == options ? void 0 : options.onSuccess
        };
        const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options;
        let order = 0;
        let newOrder = 0;
        let start = false;
        const properties = {};
        this.current.parent.mapProperties((property, key)=>{
            property['x-index'] = order;
            if (key === this.current.name) {
                ++order;
                newOrder = order;
                start = true;
            }
            ++order;
            if (start && key !== this.current.name) {
                properties[key] = property;
                this.current.parent.removeProperty(key);
            }
        });
        if (schema_namespaceObject.Schema.isSchemaInstance(schema)) {
            if (this.parentsIn(schema)) {
                this.emit('error', {
                    code: 'parent_is_not_allowed',
                    schema
                });
                return;
            }
            schema.parent.removeProperty(schema.name);
            if (removeParentsIfNoChildren) opts['removed'] = this.recursiveRemoveIfNoChildren(schema.parent, {
                breakRemoveOn
            });
            schema.parent = null;
        } else if (schema) schema = (0, external_lodash_namespaceObject.cloneDeep)(schema);
        this.prepareProperty(schema);
        const wrapped = wrap(schema);
        const s = this.current.parent.addProperty(wrapped.name || (0, schema_namespaceObject.uid)(), wrapped);
        s.parent = this.current.parent;
        s['x-index'] = newOrder;
        this.current.parent.setProperties(properties);
        const [schema1, schema2] = splitWrapSchema(s, schema);
        this.emit('insertAdjacent', {
            position: 'afterEnd',
            schema: schema2,
            wrap: schema1,
            wrapped,
            ...opts
        });
    }
    constructor(options){
        _define_property(this, "current", void 0);
        _define_property(this, "options", void 0);
        _define_property(this, "events", {});
        this.options = options;
        this.current = options.current;
    }
}
function useFindComponent() {
    const schemaOptions = (0, external_react_namespaceObject.useContext)(schema_namespaceObject.SchemaOptionsContext);
    const components = (0, external_react_namespaceObject.useMemo)(()=>(null == schemaOptions ? void 0 : schemaOptions.components) || {}, [
        schemaOptions
    ]);
    const find = (component)=>{
        if (!component) return null;
        if ('string' != typeof component) return component;
        const res = (0, external_lodash_namespaceObject.get)(components, component);
        if (!res) console.error('[tachybase]: Component "'.concat(component, '" not found'));
        return res;
    };
    return find;
}
function useDesignable() {
    const { designable, setDesignable, refresh, reset } = (0, external_react_namespaceObject.useContext)(external_context_js_namespaceObject.SchemaComponentContext);
    const schemaOptions = (0, external_react_namespaceObject.useContext)(schema_namespaceObject.SchemaOptionsContext);
    const components = (0, external_react_namespaceObject.useMemo)(()=>(null == schemaOptions ? void 0 : schemaOptions.components) || {}, [
        schemaOptions
    ]);
    const DesignableBar = (0, external_react_namespaceObject.useMemo)(()=>()=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(jsx_runtime_namespaceObject.Fragment, {}), []);
    const field = (0, schema_namespaceObject.useField)();
    const fieldSchema = (0, schema_namespaceObject.useFieldSchema)();
    const api = (0, index_js_namespaceObject.useAPIClient)();
    const { t } = (0, external_react_i18next_namespaceObject.useTranslation)();
    const dn = (0, external_react_namespaceObject.useMemo)(()=>createDesignable({
            t,
            api,
            refresh,
            current: fieldSchema,
            model: field
        }), [
        t,
        api,
        refresh,
        fieldSchema,
        field
    ]);
    (0, external_react_namespaceObject.useEffect)(()=>{
        dn.loadAPIClientEvents();
    }, [
        dn
    ]);
    return {
        dn,
        designable,
        reset,
        refresh,
        setDesignable,
        DesignableBar,
        findComponent: (0, external_react_namespaceObject.useCallback)((component)=>{
            if (!component) return null;
            if ('string' != typeof component) return component;
            return (0, external_lodash_namespaceObject.get)(components, component);
        }, [
            external_lodash_namespaceObject.get
        ]),
        on: dn.on.bind(dn),
        patch: (0, external_react_namespaceObject.useCallback)((key, value)=>{
            const update = (obj)=>{
                Object.keys(obj).forEach((k)=>{
                    const val = obj[k];
                    if ('title' === k) {
                        field.title = val;
                        fieldSchema['title'] = val;
                    }
                    if ('x-decorator-props' === k) {
                        if (!field.decoratorProps) field.decoratorProps = {};
                        if (!fieldSchema['x-decorator-props']) fieldSchema['x-decorator-props'] = {};
                        Object.keys(val).forEach((i)=>{
                            field.decoratorProps[i] = val[i];
                            fieldSchema['x-decorator-props'][i] = val[i];
                        });
                    }
                    if ('x-component-props' === k) {
                        if (!field.componentProps) field.componentProps = {};
                        if (!fieldSchema['x-component-props']) fieldSchema['x-component-props'] = {};
                        Object.keys(val).forEach((i)=>{
                            field.componentProps[i] = val[i];
                            fieldSchema['x-component-props'][i] = val[i];
                        });
                    }
                });
            };
            if ('string' == typeof key) {
                const obj = {};
                (0, external_lodash_namespaceObject.set)(obj, key, value);
                return update(obj);
            }
            update(key);
            refresh();
        }, [
            dn
        ]),
        shallowMerge: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.shallowMerge(schema);
        }, [
            dn
        ]),
        deepMerge: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.deepMerge(schema);
        }, [
            dn
        ]),
        remove: (0, external_react_namespaceObject.useCallback)((schema, options)=>{
            dn.remove(schema, options);
        }, [
            dn
        ]),
        insertAdjacent: (0, external_react_namespaceObject.useCallback)((position, schema, options)=>{
            dn.insertAdjacent(position, schema, options);
        }, [
            dn
        ]),
        insertBeforeBegin: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.insertBeforeBegin(schema);
        }, [
            dn
        ]),
        insertAfterBegin: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.insertAfterBegin(schema);
        }, [
            dn
        ]),
        insertBeforeEnd: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.insertBeforeEnd(schema);
        }, [
            dn
        ]),
        insertAfterEnd: (0, external_react_namespaceObject.useCallback)((schema)=>{
            dn.insertAfterEnd(schema);
        }, [
            dn
        ])
    };
}
var __webpack_export_target__ = exports;
for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', {
    value: true
});
