/**
 * 编辑可视区域
 */
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
const mobx_1 = require('mobx');
const _ = require('lodash');
class Viewport {
    constructor(application) {
        /**
         * 已实例化在编辑区域组件的集合
         */
        this.components = mobx_1.map();
        /**
         * 当前是否在移动元素
         */
        this.isMovingComponent = false;
        /**
         * 是否显示布局元素轮廓
         */
        this.showLayoutBorder = false;
        /**
         * 当前 viewport 正在 hover 的元素, 在 viewport 上的 x, y, width, height
         * 位置相对于 viewport
         */
        this.viewportHoverComponentSpec = {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            hovering: false
        };
        /**
         * 当前 tree 正在 hover 的元素, 在 viewport 上的 x, y, width, height
         * 位置相对于 tree
         */
        this.treeHoverComponentSpec = {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            hovering: false
        };
        /**
         * 拖拽开始时的父级元素 element
         */
        this.dragStartParentElement = null;
        /**
         * 拖拽开始时, 元素的位置
         */
        this.dragStartIndex = 0;
        /**
         * 临时存储当前 hover 元素的 element
         */
        this.currentHoverElement = null;
        /**
         * 当前编辑组件的 mapUniqueKey
         */
        this.currentEditComponentMapUniqueKey = null;
        /**
         * 最后一次选择中组件 id, 会随着取消选择变成 null
         */
        this.lastSelectMapUniqueKey = null;
        /**
         * 操作记录 是 fast-json-patch 产生的 diff 对象
         */
        this.operates = [];
        /**
         * 当前操作的 index
         */
        this.nowOperateIndex = -1;
        /**
         * 移动元素到另外一个父级是两个动作, 所以需要先存储移动到父级的 mapKey, 和移动到的位置
         */
        this.dragTargetMapUniqueKey = null;
        this.dragTargetIndex = -1;
        /**
         * 鼠标 hover 状态元素的 mapUniqueKey
         */
        this.hoveringComponentMapUniqueKey = null;
        /**
         * 当前复制的组件的信息
         */
        this.copyComponent = null;
        /**
         * 是否显示右侧附加工具条
         */
        this.isShowSidebarAddon = false;
        /**
         * 是否显示左侧附加工具条
         */
        this.isShowLeftBar = false;
        /**
         * 左侧附加工具条显示的是哪种板块
         */
        this.leftBarType = '';
        this.application = application;
    }
    /**
     * 生成根节点唯一 id
     */
    createRootUniqueId() {
        this.rootMapUniqueKey = this.createUniqueId();
        return this.rootMapUniqueKey;
    }
    /**
     * 设置根节点唯一 id
     */
    setRootUniqueId(uniqueId) {
        this.rootMapUniqueKey = uniqueId;
    }
    /**
     * 添加一个新实例元素, 不要用 componentsSet
     */
    setComponents(mapUniqueKey, componentInfo) {
        // 遍历 gaeaEdit, 如果值是 undefined || null , 设置为 isNull
        if (componentInfo.props.gaeaEdit) {
            componentInfo.props.gaeaEdit = componentInfo.props.gaeaEdit.map(gaeaEdit => {
                // 豁免一些类型
                if (['marginPadding'].findIndex(name => name === gaeaEdit.editor) > -1) {
                    gaeaEdit.isNull = false;
                }
                else {
                    if (componentInfo.props[gaeaEdit.field] === undefined || componentInfo.props[gaeaEdit.field] === null) {
                        gaeaEdit.isNull = true;
                    }
                    else {
                        gaeaEdit.isNull = false;
                    }
                }
                return gaeaEdit;
            });
        }
        this.components.set(mapUniqueKey, componentInfo);
    }
    /**
     * 生成一个唯一
     */
    createUniqueId() {
        return _.uniqueId('gaea-component-' + new Date().getTime() + '-');
    }
    /**
     * 将某个元素重置为默认配置
     */
    resetComponent(mapUniqueKey) {
        const component = this.components.get(mapUniqueKey);
        // 找到对应 class
        const ComponentClass = this.application.getComponentByUniqueKey(component.props.gaeaUniqueKey);
        // 保存操作
        this.saveOperate({
            type: 'reset',
            mapUniqueKey: mapUniqueKey,
            reset: {
                beforeProps: JSON.parse(JSON.stringify(component.props)),
                beforeName: component.props.name
            }
        });
        // 开始重置
        mobx_1.transaction(() => {
            component.props = _.cloneDeep(ComponentClass.defaultProps);
        });
    }
    /**
     * 添加 component, 根据情况分为新添加、移动已存在组件
     */
    addComponent(parentMapUniqueKey, index) {
        // 对组合特殊处理
        if (this.currentMovingComponent.uniqueKey === 'combo') {
            // 返回组合的 copy
            const copyCombo = this.createCopyComponentWithNewUniqueKey(this.application.comboComponents[this.dragStartIndex], parentMapUniqueKey);
            this.addComplexComponent(parentMapUniqueKey, copyCombo.mapUniqueKey, index, copyCombo);
            return {
                mapUniqueKey: copyCombo.mapUniqueKey,
                component: copyCombo
            };
        }
        else {
            let mapUniqueKey;
            if (this.currentMovingComponent.isNew) {
                // 添加一个全新的 component
                mapUniqueKey = this.createUniqueId();
                this.addNewComponent(mapUniqueKey, parentMapUniqueKey, this.currentMovingComponent.uniqueKey, index);
            }
            else {
                // 添加一个已存在的 component
                mapUniqueKey = this.currentMovingComponent.mapUniqueKey;
                this.addToParent(mapUniqueKey, parentMapUniqueKey, index);
            }
            return {
                mapUniqueKey: mapUniqueKey,
                component: null
            };
        }
    }
    /**
     * 同一个父级下子元素移动位置
     */
    sortComponents(parentMapUniqueKey, beforeIndex, afterIndex) {
        const layoutChilds = this.components.get(parentMapUniqueKey).layoutChilds;
        if (beforeIndex < afterIndex) {
            // 从左到右
            mobx_1.transaction(() => {
                for (let index = beforeIndex; index < afterIndex; index++) {
                    const beforeUniqueKey = layoutChilds[index];
                    const afterUniqueKey = layoutChilds[index + 1];
                    layoutChilds[index] = afterUniqueKey;
                    layoutChilds[index + 1] = beforeUniqueKey;
                }
            });
        }
        else {
            // 从右到左
            mobx_1.transaction(() => {
                for (let index = beforeIndex; index > afterIndex; index--) {
                    const beforeUniqueKey = layoutChilds[index];
                    const afterUniqueKey = layoutChilds[index - 1];
                    layoutChilds[index] = afterUniqueKey;
                    layoutChilds[index - 1] = beforeUniqueKey;
                }
            });
        }
    }
    /**
     * 开始拖拽
     */
    startDragging(childMapUniqueKey, uniqueKey, isNew, dragStartParentElement = null, dragStartIndex = 0) {
        this.isMovingComponent = true;
        this.dragStartParentElement = dragStartParentElement;
        this.dragStartIndex = dragStartIndex;
        this.currentMovingComponent = {
            mapUniqueKey: childMapUniqueKey,
            // 组件的唯一标识
            uniqueKey: uniqueKey,
            isNew: isNew
        };
    }
    /**
     * 结束拖拽
     */
    endDragging() {
        this.isMovingComponent = false;
    }
    setShowLayoutBorder(isShow) {
        this.showLayoutBorder = isShow;
    }
    /**
     * 设置根 dom 元素
     */
    setRootDomInstance(rootDomInstance) {
        this.rootDomInstance = rootDomInstance;
    }
    /**
     * 设置 viewport dom 元素
     */
    setViewportDomInstance(viewportDomInstance) {
        this.viewportDomInstance = viewportDomInstance;
    }
    /**
     * 设置 section-container dom 元素
     */
    setSectionContainerDomInstance(sectionContainerDomInstance) {
        this.sectionContainerDomInstance = sectionContainerDomInstance;
    }
    /**
     * 设置某个元素为 hover 元素
     */
    setHoverComponent(element) {
        this.currentHoverElement = element;
        this.resetComponentOutline();
    }
    /**
     * 校准当前 hover 元素边框虚线的位置
     */
    resetComponentOutline() {
        if (this.currentHoverElement === null) {
            return;
        }
        // 找到这个元素的 left, top
        const targetBoundingClientRect = this.currentHoverElement.getBoundingClientRect();
        const viewportBoundingClientRect = this.viewportDomInstance.getBoundingClientRect();
        mobx_1.transaction(() => {
            this.viewportHoverComponentSpec = {
                left: targetBoundingClientRect.left - viewportBoundingClientRect.left,
                top: targetBoundingClientRect.top - viewportBoundingClientRect.top,
                width: targetBoundingClientRect.width,
                height: targetBoundingClientRect.height,
                hovering: true
            };
        });
    }
    /**
     * 设置脱离 hover 状态
     */
    setLeaveHover() {
        this.viewportHoverComponentSpec.hovering = false;
        this.currentHoverElement = null;
    }
    /**
     * 设置 tree 脱离 hover 状态
     */
    setTreeLeaveHover() {
        this.treeHoverComponentSpec.hovering = false;
    }
    /**
     * 设置树组件跟元素
     */
    setTreeDomInstance(treeDomInstance) {
        this.treeDomInstance = treeDomInstance;
    }
    /**
     * 设置某个树元素为 hover 元素
     */
    setHoverTreeComponent(element) {
        // 找到这个元素的 left, top
        const targetBoundingClientRect = element.getBoundingClientRect();
        const treeBoundingClientRect = this.treeDomInstance.getBoundingClientRect();
        mobx_1.transaction(() => {
            this.treeHoverComponentSpec = {
                left: targetBoundingClientRect.left - treeBoundingClientRect.left,
                top: targetBoundingClientRect.top - treeBoundingClientRect.top,
                width: element.clientWidth,
                height: element.clientHeight,
                hovering: true
            };
        });
    }
    /**
     * 设置当前编辑组件
     */
    setCurrentEditComponentMapUniqueKey(mapUniqueKey) {
        this.currentEditComponentMapUniqueKey = mapUniqueKey;
        // 出现附加工具条，因为编辑框在这里
        this.showSidebarAddon();
    }
    /**
     * 取消编辑当前组件
     */
    cancelEditComponent() {
        this.currentEditComponentMapUniqueKey = null;
        this.hideSidebarAddon();
        if (this.lastSelectMapUniqueKey !== null) {
            this.application.event.emit(this.application.event.changeComponentSelectStatusEvent, {
                mapUniqueKey: this.lastSelectMapUniqueKey,
                selected: false
            });
            this.setLastSelectMapUniqueKey(null);
        }
    }
    /**
     * 根据子元素的 mapUniqueKey 寻找从跟元素开始的路径
     * 因为渲染的时候是嵌套渲染的, 从打平 map 中找到关系路径, 便于元素直接搜索任意子组件
     */
    findComponentPathFromRoot(mapUniqueKey) {
        let finderPath = [mapUniqueKey];
        let nowComponent = this.components.get(mapUniqueKey);
        // 如果已经是根元素, 直接返回空数组
        if (nowComponent.parentMapUniqueKey === null) {
            return [];
        }
        // 直到父级是根元素为止
        while (this.components.get(nowComponent.parentMapUniqueKey).parentMapUniqueKey !== null) {
            finderPath.unshift(nowComponent.parentMapUniqueKey);
            nowComponent = this.components.get(nowComponent.parentMapUniqueKey);
        }
        return finderPath;
    }
    /**
     * 编辑当前组件, 某个选项的值，附带保存历史
     */
    updateComponentOptionsValue(editOptions, value) {
        let componentInfo = this.components.get(this.currentEditComponentMapUniqueKey);
        const oldValue = JSON.parse(JSON.stringify(componentInfo.props));
        this.updateComponentOptionsValueByOptions(this.currentEditComponentMapUniqueKey, editOptions, value);
        const newValue = JSON.parse(JSON.stringify(componentInfo.props));
        // 保存操作
        this.saveOperate({
            type: 'update',
            mapUniqueKey: this.currentEditComponentMapUniqueKey,
            update: {
                editOptions: JSON.parse(JSON.stringify(editOptions)),
                oldValue: oldValue,
                newValue: newValue
            }
        });
    }
    /**
     * 根据 editOption 修改值
     */
    updateComponentOptionsValueByOptions(mapUniqueKey, editOptions, value) {
        let componentInfo = this.components.get(mapUniqueKey);
        if (value !== null) {
            // 不能让 null 设置无效, 所以非 null 才做转换
            switch (editOptions.type) {
                case 'string':
                    value = value.toString();
                    break;
                case 'number':
                    value = Number(value);
                    break;
                case 'boolean':
                    value = Boolean(value);
                    break;
            }
        }
        // 修改组件值
        switch (editOptions.editor) {
            case 'marginPadding':
                componentInfo.props['marginLeft'] = value['marginLeft'];
                componentInfo.props['marginTop'] = value['marginTop'];
                componentInfo.props['marginRight'] = value['marginRight'];
                componentInfo.props['marginBottom'] = value['marginBottom'];
                componentInfo.props['paddingLeft'] = value['paddingLeft'];
                componentInfo.props['paddingTop'] = value['paddingTop'];
                componentInfo.props['paddingRight'] = value['paddingRight'];
                componentInfo.props['paddingBottom'] = value['paddingBottom'];
                break;
            default:
                componentInfo.props[editOptions.field] = value;
        }
    }
    /**
     * 设置最后一次高亮选择组件 id
     */
    setLastSelectMapUniqueKey(mapUniqueKey) {
        this.lastSelectMapUniqueKey = mapUniqueKey;
    }
    /**
     * 获取增量编辑信息
     */
    getIncrementComponentsInfo() {
        // 获取 components 的 map, 但是要把 options 中除了 value 以外字段都干掉
        const cloneComponents = JSON.parse(JSON.stringify(this.components.toJSON()));
        Object.keys(cloneComponents).map(key => {
            // icon 不会变
            delete cloneComponents[key].props.icon;
            // 获取这个组件的 defaultProps
            const defaultProps = this.application.getComponentByUniqueKey(cloneComponents[key].props.gaeaUniqueKey).defaultProps;
            // 如果 name 相同, 删了
            if (cloneComponents[key].props.name == defaultProps.name) {
                delete cloneComponents[key].props.name;
            }
            // 对 props 进行瘦身
            const props = cloneComponents[key].props;
            props && Object.keys(props).forEach(propsKey => {
                // gaeaUniqueKey 必须留着
                if (propsKey === 'gaeaUniqueKey') {
                    return;
                }
                // gaeaEdit 直接删
                if (propsKey === 'gaeaEdit') {
                    delete props[propsKey];
                    return;
                }
                // 判断值相等就行了
                if (props[propsKey] == defaultProps[propsKey]) {
                    // 如果和初始值相同, 就销毁
                    delete props[propsKey];
                }
            });
            // layoutChilds 长度为 0 就干掉
            if (cloneComponents[key].layoutChilds.length === 0) {
                delete cloneComponents[key].layoutChilds;
            }
            // 如果 props 已经被删完了, 直接删掉 props
            if (!props || Object.keys(props).length === 0) {
                delete cloneComponents[key].props.options;
            }
        });
        return cloneComponents;
    }
    /**
     * 添加一个新组件, 这个方法会在从工具栏拖拽新组件过来时使用
     */
    addNewComponent(mapUniqueKey, parentMapUniqueKey, uniqueId, index) {
        // 找到操作组件的 class
        const ComponentClass = this.application.getComponentByUniqueKey(uniqueId);
        // 从 startDragging 设置的 uniqueKey 生成新组件并且绑定上
        const newProps = _.cloneDeep(ComponentClass.defaultProps);
        let component = {
            props: newProps,
            parentMapUniqueKey: parentMapUniqueKey,
            layoutChilds: []
        };
        if (uniqueId === 'gaea-layout') {
            // 如果是个布局元素, 将其 layoutChilds 设置为数组
            component.layoutChilds = [];
        }
        mobx_1.transaction(() => {
            this.setComponents(mapUniqueKey, component);
        });
        // 在父级中插入子元素
        this.components.get(parentMapUniqueKey).layoutChilds.splice(index, 0, mapUniqueKey);
    }
    /**
     * 添加一个已存在的 component 到它的父级
     * 需要保证这个组件的信息已经是完备的
     * 1. 存在于 this.components 中
     * 2. 如果是布局组件, 所有子元素也都存在于 this.components 中
     */
    addToParent(mapUniqueKey, parentMapUniqueKey, index) {
        // 修改那个元素的父级
        this.components.get(mapUniqueKey).parentMapUniqueKey = parentMapUniqueKey;
        // 在父级中插入子元素
        this.components.get(parentMapUniqueKey).layoutChilds.splice(index, 0, mapUniqueKey);
    }
    /**
     * 添加一个复杂组件
     * 这个方法会在恢复元素时使用, 保证所有 key 都原封不动的恢复
     */
    addComplexComponent(parentMapUniqueKey, mapUniqueKey, index, componentFullInfo) {
        // 先把子元素添加回来
        Object.keys(componentFullInfo.childs).forEach(childMapUniqueKey => {
            this.setComponents(childMapUniqueKey, _.cloneDeep(componentFullInfo.childs[childMapUniqueKey]));
        });
        // 再把这个组件添加回来
        this.setComponents(mapUniqueKey, _.cloneDeep(componentFullInfo.componentInfo));
        // 加到父级上
        this.addToParent(mapUniqueKey, parentMapUniqueKey, index);
    }
    /**
     * 初始化上次操作记录
     */
    initLastOperateComponents(lastOperateComponents) {
        this.lastOperateComponents = lastOperateComponents;
    }
    /**
     * 保存操作记录 需要保存的时机:
     * 新增元素 ok
     * 移动元素 ok
     * 交换元素 ok
     * 删除元素 ok
     * 修改元素 ok
     */
    saveOperate(diff) {
        // 如果后面还有操作, 直接清空
        this.operates.splice(this.nowOperateIndex + 1);
        this.operates.push(diff);
        this.nowOperateIndex = this.operates.length - 1;
    }
    /**
     * 删除 component
     */
    deleteComponent(mapUniqueKey, deleteChildComponents = {}) {
        // 从父级删除这个 child
        // 能删除的都不是根元素, 一定有 parentMapUniqueKey 这个属性
        const parentComponent = this.components.get(this.components.get(mapUniqueKey).parentMapUniqueKey);
        const childIndex = parentComponent.layoutChilds.findIndex(item => item === mapUniqueKey);
        parentComponent.layoutChilds.splice(childIndex, 1);
        // 删除子元素
        const component = this.components.get(mapUniqueKey);
        if (component.props.gaeaUniqueKey === 'gaea-layout') {
            JSON.parse(JSON.stringify(component.layoutChilds)).forEach((componentMapUniqueKey) => {
                // 记录这个组件的信息
                deleteChildComponents[componentMapUniqueKey] = JSON.parse(JSON.stringify(this.components.get(componentMapUniqueKey)));
                // 删除之
                this.deleteComponent(componentMapUniqueKey, deleteChildComponents);
            });
        }
        this.components.delete(mapUniqueKey);
        return deleteChildComponents;
    }
    /**
     * 操作 undo
     */
    undo() {
        if (this.nowOperateIndex <= -1) {
            return;
        }
        // 先取消编辑状态
        this.cancelEditComponent();
        const operate = this.operates[this.nowOperateIndex];
        switch (operate.type) {
            case 'add':
                this.deleteComponent(operate.mapUniqueKey);
                break;
            case 'update':
                this.components.get(operate.mapUniqueKey).props = _.cloneDeep(operate.update.oldValue);
                break;
            case 'exchange':
                this.sortComponents(operate.mapUniqueKey, operate.exchange.newIndex, operate.exchange.oldIndex);
                break;
            case 'move':
                // 找到这个元素现在的 mapUniqueKey
                const mapUniqueKey = this.components.get(operate.move.targetParentMapUniqueKey).layoutChilds.splice(operate.move.targetIndex, 1)[0];
                // 添加过去
                this.addToParent(mapUniqueKey, operate.move.sourceParentMapUniqueKey, operate.move.sourceIndex);
                break;
            case 'remove':
                this.addComplexComponent(operate.remove.parentMapUniqueKey, operate.mapUniqueKey, operate.remove.index, operate.remove);
                break;
            case 'paste':
                this.deleteComponent(operate.mapUniqueKey);
                break;
            case 'reset':
                this.components.get(operate.mapUniqueKey).props = operate.reset.beforeProps;
                break;
            case 'addCombo':
                this.deleteComponent(operate.mapUniqueKey);
                break;
        }
        this.nowOperateIndex -= 1;
    }
    /**
     * 操作 redo
     */
    redo() {
        if (this.nowOperateIndex >= this.operates.length - 1) {
            return;
        }
        // 先取消编辑状态
        this.cancelEditComponent();
        this.nowOperateIndex += 1;
        const operate = this.operates[this.nowOperateIndex];
        switch (operate.type) {
            case 'add':
                this.addNewComponent(operate.mapUniqueKey, operate.add.parentMapUniqueKey, operate.add.uniqueId, operate.add.index);
                break;
            case 'update':
                this.components.get(operate.mapUniqueKey).props = _.cloneDeep(operate.update.newValue);
                break;
            case 'exchange':
                this.sortComponents(operate.mapUniqueKey, operate.exchange.oldIndex, operate.exchange.newIndex);
                break;
            case 'move':
                // 找到这个元素现在的 mapUniqueKey
                const mapUniqueKey = this.components.get(operate.move.sourceParentMapUniqueKey).layoutChilds.splice(operate.move.sourceIndex, 1)[0];
                // 添加过去
                this.addToParent(mapUniqueKey, operate.move.targetParentMapUniqueKey, operate.move.targetIndex);
                break;
            case 'remove':
                this.deleteComponent(operate.mapUniqueKey);
                break;
            case 'paste':
                this.addComplexComponent(operate.paste.parentMapUniqueKey, operate.mapUniqueKey, operate.paste.index, operate.paste);
                break;
            case 'reset':
                const ComponentClass = this.application.getComponentByUniqueKey(operate.reset.beforeProps.gaeaUniqueKey);
                this.components.get(operate.mapUniqueKey).props = _.cloneDeep(ComponentClass.defaultProps);
                break;
            case 'addCombo':
                this.addComplexComponent(operate.addCombo.parentMapUniqueKey, operate.mapUniqueKey, operate.addCombo.index, operate.addCombo.componentInfo);
                break;
        }
    }
    /**
     * 是否能 undo
     */
    get canUndo() {
        return this.nowOperateIndex > -1;
    }
    /**
     * 是否能 redo
     */
    get canRedo() {
        return this.nowOperateIndex < this.operates.length - 1;
    }
    /**
     * 设置元素信息: 这个元素正在移动到另一个父级
     */
    setDragTarget(mapUniqueKey, index) {
        this.dragTargetMapUniqueKey = mapUniqueKey;
        this.dragTargetIndex = index;
    }
    /**
     * 设置鼠标 hover 状态元素的 mapUniqueKey
     */
    setHoveringComponentMapUniqueKey(mapUniqueKey) {
        this.hoveringComponentMapUniqueKey = mapUniqueKey;
    }
    /**
     * 复制组件
     */
    copy(mapUniqueKey) {
        if (!mapUniqueKey) {
            return true;
        }
        this.copyComponent = this.getComponentFullInfoByMapUniqueKey(mapUniqueKey);
    }
    /**
     * 返回一个新的复制对象, 把所有 mapUniqueKey 都换成新的, 但引用关系保持不变
     */
    createCopyComponentWithNewUniqueKey(originComponent, parentMapUniqueKey) {
        // 保持父子级引用关系不变, 重新生成 mapUniqueKey
        // [oldMapUniqueKey => newMapUniqueKey]
        const uniqueKeyMap = new Map();
        uniqueKeyMap.set(originComponent.mapUniqueKey, this.createUniqueId());
        if (originComponent.componentInfo.props.gaeaUniqueKey === 'gaea-layout') {
            Object.keys(originComponent.childs).forEach(childMapUniqueKey => {
                uniqueKeyMap.set(childMapUniqueKey, this.createUniqueId());
            });
        }
        // 更新 childs 的 mapUniqueKey
        let childs = {};
        Object.keys(originComponent.childs).forEach(mapUniqueKey => {
            const originChild = originComponent.childs[mapUniqueKey];
            childs[uniqueKeyMap.get(mapUniqueKey)] = {
                parentMapUniqueKey: uniqueKeyMap.get(originChild.parentMapUniqueKey),
                props: JSON.parse(JSON.stringify(originChild.props)),
                layoutChilds: originChild.layoutChilds.map(childMapUniqueKey => uniqueKeyMap.get(childMapUniqueKey))
            };
        });
        // 生成新的 copyComponent
        let newCopyComponent = {
            mapUniqueKey: uniqueKeyMap.get(originComponent.mapUniqueKey),
            componentInfo: {
                parentMapUniqueKey: parentMapUniqueKey,
                props: JSON.parse(JSON.stringify(originComponent.componentInfo.props)),
                layoutChilds: originComponent.componentInfo.layoutChilds.map(childMapUniqueKey => uniqueKeyMap.get(childMapUniqueKey))
            },
            childs: childs
        };
        return newCopyComponent;
    }
    /**
     * 粘贴到某个组件上
     */
    paste(parentMapUniqueKey) {
        if (!parentMapUniqueKey) {
            return true;
        }
        if (!this.copyComponent) {
            return true;
        }
        const parentComponent = this.components.get(parentMapUniqueKey);
        // 必须是布局组件
        if (parentComponent.props.gaeaUniqueKey !== 'gaea-layout') {
            return false;
        }
        // 返回一个新 mapUniqueKey 的 copy 对象
        const newCopyComponent = this.createCopyComponentWithNewUniqueKey(this.copyComponent, parentMapUniqueKey);
        // 获得父级组件的子元素长度
        const parentChildCount = this.components.get(parentMapUniqueKey).layoutChilds.length;
        this.addComplexComponent(parentMapUniqueKey, newCopyComponent.mapUniqueKey, parentChildCount, newCopyComponent);
        // 记录日志
        this.saveOperate({
            type: 'paste',
            mapUniqueKey: newCopyComponent.mapUniqueKey,
            paste: {
                parentMapUniqueKey: parentMapUniqueKey,
                index: parentChildCount,
                mapUniqueKey: newCopyComponent.mapUniqueKey,
                componentInfo: newCopyComponent.componentInfo,
                childs: newCopyComponent.childs
            }
        });
        return true;
    }
    /**
     * 获取一个已存在组件的完整信息
     */
    getComponentFullInfoByMapUniqueKey(mapUniqueKey) {
        const componentInfo = this.components.get(mapUniqueKey);
        // 子元素信息
        let childs = {};
        const mapChilds = (component, childs) => {
            if (component.props.gaeaUniqueKey === 'gaea-layout') {
                JSON.parse(JSON.stringify(component.layoutChilds)).forEach((componentMapUniqueKey) => {
                    const childInfo = this.components.get(componentMapUniqueKey);
                    childs[componentMapUniqueKey] = JSON.parse(JSON.stringify(childInfo));
                    mapChilds(childInfo, childs);
                });
            }
        };
        mapChilds(componentInfo, childs);
        return {
            mapUniqueKey: mapUniqueKey,
            componentInfo: JSON.parse(JSON.stringify(componentInfo)),
            childs: childs
        };
    }
    showSidebarAddon() {
        this.isShowSidebarAddon = true;
        // 显示工具条动画是 200 毫秒
        setTimeout(() => {
            // 动画结束后，重置外边框位置
            this.resetComponentOutline();
        }, 210);
    }
    hideSidebarAddon() {
        this.isShowSidebarAddon = false;
        setTimeout(() => {
            // 动画结束后，重置外边框位置
            this.resetComponentOutline();
        }, 210);
    }
    showLeftBar(leftBarType) {
        this.leftBarType = leftBarType;
        this.isShowLeftBar = true;
    }
    hideLeftBar() {
        this.leftBarType = '';
        this.isShowLeftBar = false;
    }
}
__decorate([
    mobx_1.observable
], Viewport.prototype, "components", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "rootMapUniqueKey", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "isMovingComponent", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "showLayoutBorder", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "viewportHoverComponentSpec", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "treeHoverComponentSpec", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "currentEditComponentMapUniqueKey", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "nowOperateIndex", void 0);
__decorate([
    mobx_1.computed
], Viewport.prototype, "canUndo", null);
__decorate([
    mobx_1.computed
], Viewport.prototype, "canRedo", null);
__decorate([
    mobx_1.observable
], Viewport.prototype, "isShowSidebarAddon", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "isShowLeftBar", void 0);
__decorate([
    mobx_1.observable
], Viewport.prototype, "leftBarType", void 0);
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Viewport;
