"use strict";
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.afterPlacement = exports.inPlacement = exports.beforePlacement = exports.dropComponent = void 0;
const utils_1 = require("../utils");
const add_1 = require("./add");
/**
 * drop component get the effects(nodes)
 * @param dnd dnd data
 * @param opt options
 * @returns effects
 */
const dropComponent = (dnd, opt) => {
    const { dragInfo, dropIn, placement } = dnd;
    const { type = 'add', detail } = dragInfo || {};
    if (!detail) {
        return [];
    }
    const { formattedData, file } = opt;
    const { componentMap } = formattedData || {};
    let node = {};
    if (type === 'add') {
        node = (0, add_1.addComponent)(detail, { componentMap });
    }
    else {
        // TODO: style node, need to general
        const { __styleNode } = detail;
        if (__styleNode) {
            node = __styleNode;
        }
        else {
            node = detail;
        }
    }
    const effects = placementNode(node, placement, { dropIn: dropIn, formattedData, file });
    return effects;
};
exports.dropComponent = dropComponent;
/**
 * placement
 * for get the effect node
 * @param node
 * @param placement  placement: 'before'|'after'|'in'
 * @param opt
 * @returns
 */
const placementNode = (node, placement = 'in', opt) => {
    const { formattedData, dropIn, file } = opt;
    if (!dropIn) {
        // TODO: need to clean
        if (file.type === 'page') {
            const pageNode = Object.values(formattedData.originPageNodeMap).find((item) => item.name === 'page' || item.name === '');
            if (pageNode) {
                node.extension.parentId = pageNode.id;
            }
        }
        return [node];
    }
    const dropInTemplate = !!formattedData.templateNodeMap[dropIn.id];
    if (dropInTemplate) {
        // pageNode
        const pageNode = Object.values(formattedData.originPageNodeMap).find(item => item.name === 'page' || item.name === '');
        if (pageNode) {
            node.extension.parentId = pageNode.id;
        }
        return [node];
    }
    // drop in the page node
    const dropInComponent = formattedData.componentMap[dropIn.name];
    if (dropInComponent && dropInComponent.type === 'systemComponent' && dropInComponent.name === 'page') {
        return (0, exports.inPlacement)(node, dropIn, formattedData);
    }
    let effects = [];
    if (placement === 'before') {
        effects = (0, exports.beforePlacement)(node, dropIn, formattedData);
    }
    else if (placement === 'in') {
        effects = (0, exports.inPlacement)(node, dropIn, formattedData);
    }
    else if (placement === 'after') {
        effects = (0, exports.afterPlacement)(node, dropIn, formattedData);
    }
    return effects;
};
const beforePlacement = (node, dropIn, formattedData) => {
    var _a;
    const { id: dropInId, extension } = dropIn;
    const { sort = 0, parentId = '', extendId = '' } = extension || {};
    let effects = [];
    const dropInExtend = !!extendId || formattedData.extendPageNodeMap[dropInId];
    node.extension.parentId = parentId;
    if (dropInExtend) {
        const preNode = getPreNode(dropIn, formattedData);
        const preNodeSort = ((_a = preNode === null || preNode === void 0 ? void 0 : preNode.extension) === null || _a === void 0 ? void 0 : _a.sort) || 0;
        node.extension.sort = preNode ? preNodeSort + 1 : 1;
        effects.push(node);
    }
    else {
        node.extension.sort = sort || 0;
        effects.push(node);
        const preNodeSort = node.extension.sort;
        // next brothers
        const brothers = [...getChildren(parentId, formattedData)];
        const idx = brothers.findIndex((item) => item.id === node.id); // same level move
        if (idx > -1) {
            brothers.splice(idx, 1);
        }
        effects = effects.concat(getNextEffects(dropInId, preNodeSort, brothers));
    }
    return effects;
};
exports.beforePlacement = beforePlacement;
const inPlacement = (node, dropIn, formattedData) => {
    var _a, _b, _c, _d, _e;
    const dropInExtend = !!((_a = dropIn.extension) === null || _a === void 0 ? void 0 : _a.extendId);
    node.extension.parentId = dropIn.id;
    if (dropInExtend) {
        const children = getChildren(dropIn.id, formattedData);
        const lastNode = children[(children === null || children === void 0 ? void 0 : children.length) || 0];
        if (!!((_b = lastNode === null || lastNode === void 0 ? void 0 : lastNode.extension) === null || _b === void 0 ? void 0 : _b.extendId)) {
            node.extension.sort = (((_c = lastNode === null || lastNode === void 0 ? void 0 : lastNode.extension) === null || _c === void 0 ? void 0 : _c.sort) || 100) + 1;
        }
        else {
            const existExtendNode = children.find((item) => !!item.extension.extendId);
            node.extension.sort = (((_d = lastNode === null || lastNode === void 0 ? void 0 : lastNode.extension) === null || _d === void 0 ? void 0 : _d.sort) || 0) + (existExtendNode ? 1 : 100);
        }
    }
    else {
        node.extension.sort = ((((_e = dropIn.childIds) === null || _e === void 0 ? void 0 : _e.length) || 0) + 1) * 100;
    }
    return [node];
};
exports.inPlacement = inPlacement;
const afterPlacement = (node, dropIn, formattedData) => {
    const { id: dropInId, extension } = dropIn;
    const { sort: dropInNodeSort = 0, parentId = '', extendId = '' } = extension || {};
    const dropInExtend = !!extendId || formattedData.extendPageNodeMap[dropInId];
    let effects = [];
    // next brothers
    const brothers = [...getChildren(parentId, formattedData)];
    const idx = brothers.findIndex((item) => item.id === node.id); // same level move
    if (idx > -1) {
        brothers.splice(idx, 1);
    }
    const curNodeSort = dropInNodeSort + (dropInExtend ? 1 : 100);
    node.extension.sort = curNodeSort;
    node.extension.parentId = parentId;
    effects.push(node);
    effects = effects.concat(getNextEffects(dropInId, curNodeSort, brothers, true));
    return effects;
};
exports.afterPlacement = afterPlacement;
const getNode = (id, formattedData) => {
    return (0, utils_1.findStructureById)(formattedData.formattedSchemas, id);
};
const getChildren = (id, formattedData) => {
    var _a;
    let parent = getNode(id, formattedData);
    if (!parent) {
        parent = formattedData.originPageNodeMap[id];
        if (parent) {
            return ((_a = parent.childIds) === null || _a === void 0 ? void 0 : _a.map((item) => formattedData.originPageNodeMap[item])) || [];
        }
        const extendNode = formattedData.extendPageNodeMap[id];
        if (extendNode) {
            return [];
        }
        return [...(formattedData.formattedSchemas || [])];
    }
    return [...(parent.children || [])];
};
const getPreNode = (node, formattedData) => {
    const parent = getNode(node.extension.parentId || '', formattedData);
    const childIds = (parent === null || parent === void 0 ? void 0 : parent.childIds) || [];
    const preId = childIds[childIds.indexOf(node.id) - 1];
    const preNode = getNode(preId, formattedData);
    return preNode;
};
/**
 * get the next effect nodes by placement changed
 * end by the extend node
 * @param startId
 * @param startSort
 * @param brothers
 * @param next
 * @returns
 */
const getNextEffects = (startId, startSort, brothers = [], next) => {
    const effects = [];
    const idx = brothers.findIndex((item) => item.id === startId);
    const nextChildren = idx > -1 ? brothers.splice(next ? idx + 1 : idx, brothers.length) : brothers;
    const nextExtendIdx = nextChildren.findIndex((item) => !!item.extension.extendId);
    if (nextExtendIdx > -1) {
        nextChildren.forEach((item, idx) => {
            if (idx < nextExtendIdx) {
                const { extension, children } = item, rest = __rest(item, ["extension", "children"]);
                effects.push(Object.assign(Object.assign({}, rest), { extension: Object.assign(Object.assign({}, extension), { sort: startSort + idx + 1 }) }));
            }
        });
    }
    else {
        getSortEffects(nextChildren, effects, (idx) => startSort + (idx + 1) * 100);
    }
    return effects;
};
/**
 * get the effect node  by sort change
 * @param list
 * @param effects
 * @param sort
 */
const getSortEffects = (list = [], effects = [], sort) => {
    list.forEach((item, idx) => {
        const { extension, children } = item, rest = __rest(item, ["extension", "children"]);
        effects.push(Object.assign(Object.assign({}, rest), { extension: Object.assign(Object.assign({}, extension), { sort: sort(idx) }) }));
    });
};
