<template>
    <el-row>
        <el-col :span="10" class="transfer-panel">
            <!--<el-input
                placeholder="输入关键字进行过滤"
                v-model="filterText">
        </el-input>-->
            <el-tree
                :filter-node-method="filterNode"
                v-if="reRender"
                :data="treeLeft"
                :props="defaultProps"
                node-key="id"
                show-checkbox
                @node-expand="(node)=>{expand(node,expandedKeys.common)}"
                @node-collapse="(node)=>{collapse(node,expandedKeys.common)}"
                :default-expanded-keys="expandedKeys.common"
                ref="treeLeft"
            >
            </el-tree>
            <!--default-expand-all-->
        </el-col>
        <el-col :span="4" class="transfer-panel-middle">
            <div class="transfer-buttons">
                <slot></slot>
            </div>
        </el-col>
        <el-col :span="10" class="transfer-panel">
            <el-tree
                v-if="reRender"
                :data="treeRight"
                :props="defaultProps"
                node-key="id"
                show-checkbox
                @node-expand="(node)=>{expand(node,expandedKeys.common)}"
                @node-collapse="(node)=>{collapse(node,expandedKeys.common)}"
                :default-expanded-keys="expandedKeys.common"
                ref="treeRight"
            >
            </el-tree>
        </el-col>
    </el-row>
</template>

<script>
import * as ObjUtil from "../../../util/pattern/object";
export default {
    name: "veDoubleTree",
    data() {
        return {
            defaultProps: {
                children: 'children',
                label: 'label'
            },
            treeLeft: [],
            treeRight: [],
            reRender: true,
            expandedKeys: {
                common: [],
                left: [],
                right: []
            }
        }
    },
    created() {
    },
    mounted() {
    },
    methods: {
        init(treeLeft, treeRight) {
            this.treeLeft = treeLeft;
            this.treeRight = treeRight;
            this.expandedKeys = {
                common: [],
                left: [],
                right: []
            };
        },
        filterNode(value, data) {
            if (!value) return true;
            return data.label.indexOf(value) !== -1;
        },
        getTree(list) {
            let data = [];
            let dataMap = {};
            for (let i = 0; i < list.length; i++) {
                let node = list[i];
                node.children = [];
                node.pid = node.parent ? node.parent.id : -1;
                dataMap[node.id] = node;
            }
            for (let id in dataMap) {
                let node = dataMap[id];
                node.parent = dataMap[node.pid];
                if (node.parent) {
                    node.parent.children.push(node);
                } else {
                    data.push(node);
                }
            }
            return data;
        },
        getCheckTree(nodes) {
            let nodeMap = {};
            let data = [];
            for (let i = 0; i < nodes.length; i++) {
                let node = nodes[i];
                while (node) {
                    nodeMap[node.id] = node;
                    node = node.parent;
                }
            }
            for (let id in nodeMap) data.push(nodeMap[id]);
            return this.getTree(this.copy(data));

        },
        getNodes(list) {
            let nodeMap = {};
            let getNodes_ = function (list) {
                for (let i = 0; i < list.length; i++) {
                    let node = list[i];
                    nodeMap[node.id] = node;
                    getNodes_(node.children || [])
                }
            };
            getNodes_(list);
            let data = [];
            for (let id in nodeMap) {
                let node = nodeMap[id];
                data.push(node);
            }
            return data;
        },
        mergeTree(data1, data2) {
            return this.getTree(this.copy(this.getNodes([...data1, ...data2])));
        },
        copy(data) {
            return ObjUtil.parse(ObjUtil.stringify(data));
        },
        moveCheckFromLeft() {
            let checkNodes = this.$refs.treeLeft.getCheckedNodes();
            let nodes = this.getCheckTree(checkNodes);
            this.treeRight = this.mergeTree(this.treeRight, nodes);
            this.remove(checkNodes, this.treeLeft);
            this.reRender = false;
            this.$nextTick(() => {
                this.reRender = true;
            })
        },
        remove(nodes, treeData) {
            for (let i = 0; i < nodes.length; i++) {
                let node = nodes[i];
                const parent = node.parent;
                const children = (parent || {children: treeData}).children;
                const index = children.findIndex((d) => {
                    return d.id === node.id
                });
                children.splice(index, 1);
            }
        },
        moveAllFromLeft() {
            this.treeRight = this.mergeTree(this.treeRight, this.treeLeft);
            this.treeLeft = [];
            this.reRender = false;
            this.$nextTick(() => {
                this.reRender = true;
            })
        },
        moveAllFromRight() {
            this.treeLeft = this.mergeTree(this.treeLeft, this.treeRight);
            this.treeRight = [];
            this.reRender = false;
            this.$nextTick(() => {
                this.reRender = true;
            })
        },
        moveCheckFromRight() {
            let checkNodes = this.$refs.treeRight.getCheckedNodes();
            let nodes = this.getCheckTree(checkNodes);
            this.treeLeft = this.mergeTree(this.treeLeft, nodes);
            this.remove(checkNodes, this.treeRight);
            this.reRender = false;
            this.$nextTick(() => {
                this.reRender = true;
            })
        },
        expand(node, list) {
            list.push(node.id);
        },
        collapse(node, list) {
            const index = list.findIndex((d) => {
                return d === node.id
            });
            list.splice(index, 1);
        },
        getLeftTreeData() {
            return this.treeLeft;
        },
        getLeftNodes() {
            return this.getNodes(this.treeLeft);
        },
        getRightTreeData() {
            return this.treeRight;
        },
        getRightNodes() {
            return this.getNodes(this.treeRight);
        },
    },
}
</script>
<style lang="less" scoped>
.transfer-panel {
    height: 500px;
    overflow: auto;
    border: 1px solid #ebeef5;
    border-radius: 4px;
}

.transfer-panel-middle {
    height: 500px;
    display: table;

    .transfer-buttons {
        display: table-cell;
        vertical-align: middle;
        text-align: center;
    }
}
</style>
