<!-- Created by henian.xu on 2017/6/6. -->
<!--<template>
    <el-table
        class="tree-grid"
        v-bind="$attrs"
        :data="this.tableData"
    >
        <el-table-column
            class-name="column-expand"
            v-if="!!this.expandProp"
            :prop="this.expandProp.prop"
            :label="this.expandProp.label"
            :width="this.expandProp.width"
            :min-width="this.expandProp.minWidth"
        >
            <template slot-scope="scope">
                <div
                    :class="['indent-space',{'leaf':scope.row[prop.isLeaf]}]"
                    :style="{
                        'padding-left':(14 * scope.row[prop.level]) + 'px'
                    }"
                    @click="onRow(scope)"
                >
                    <i
                        v-if="!scope.row[prop.isLeaf]"
                        :class="{
                            'el-icon-caret-right':!scope.row[prop.expand],
                            'el-icon-caret-bottom':scope.row[prop.expand]
                        }"
                    />
                    <i
                        v-else
                        class="el-icon-caret-right"
                        style="opacity: 0"
                    />
                    <div class="node-label">
                        {{ scope.row[expandProp.prop] }}
                    </div>
                </div>
            </template>
        </el-table-column>

        <slot />
    </el-table>
</template>-->

<script lang="jsx">
import './elTableHook'

export default {
    name: 'TreeTable',
    data() {
        return {
            // tableData: [],
            rootNode: [],
        };
    },
    props: {
        data: {
            type: Array,
            default() {
                return [];
            },
        },
        // 展开节点属性
        expandProps: {
            type: Object,
            default() {
                return {};
            },
        },
        props: {
            type: Object,
            default() {
                return {
                    children: 'children',
                    expand: 'expand',
                    level: 'lv',
                    isLeaf: 'isLeaf',
                };
            },
        },
        rootLevel: {
            type: Number,
            default: 1,
        },
        lazyLoad: {
            type: Function,
            default: null,
        },
        initNotLoad: {
            type: Boolean,
            default: false,
        },
    },
    computed: {
        expandProp() {
            const { expandProps } = this;
            return {
                prop: '',
                label: '',
                width: expandProps.minWidth ? null : 48,
                minWidth: 48,
                ...expandProps,
            };
        },
        prop() {
            const { props } = this;
            return {
                children: 'children',
                expand: 'expand',
                level: 'lv',
                isLeaf: 'isLeaf',
                ...props,
            };
        },
        isLazy() {
            return typeof this.lazyLoad === 'function';
        },
        tableData: {
            get() {
                const { rootNode } = this;
                return this.buildTableData(rootNode);
            },
        },
    },
    methods: {
        buildTableData(list, parent, res = []) {
            parent = parent || {
                isRoot: true,
                children: this.rootNode,
            };
            const { prop } = this;
            const {
                children: childrenKey, expand: expandKey, level: levelKey, isLeaf: isLeafKey,
            } = prop;
            list.forEach((item, index) => {
                this.$set(item, '_index', index);
                this.$set(item, '_parent', parent);
                this.$set(item, expandKey, !!item[expandKey]);
                this.$set(item, isLeafKey, item[isLeafKey] === null ? true : item[isLeafKey]);
                this.$set(item, childrenKey, item[childrenKey] || null);
                item[levelKey] = item[levelKey] || this.rootLevel;
                this.$set(item, levelKey, item[levelKey] || this.rootLevel);
                res.push(item);
                if (item[childrenKey] && item[expandKey]) {
                    this.buildTableData(item[childrenKey], item, res);
                }
            });
            return res;
        },
        /**
         * [懒加载]加载节点数据
         * @param row 为假侧更新根节点
         */
        loadNode(row) {
            const { lazyLoad, isLazy, prop } = this;
            if (!isLazy) return Promise.resolve();
            return lazyLoad({ row }).then((data) => {
                if (row) {
                    row[prop.children] = data;
                    // 当然新增子节点时 isLeaf 应该轩为 false
                    row[prop.isLeaf] = false;
                } else {
                    this.rootNode = data;
                }
                return Promise.resolve(data);
            });
        },
        // 行被点击
        onRow(scope) {
            const { prop } = this;
            const { row } = scope;
            const isLeaf = row[prop.isLeaf];
            const isExpand = row[prop.expand];
            if (isLeaf) return; // 如果是叶节点立即返回
            if (isExpand) {
                // collapseNode
                row[prop.expand] = false;
            } else {
                // expandNode
                row[prop.expand] = true;
                if (!row[prop.children]) this.loadNode(row);
            }
        },
        refreshChildren(row) {
            const { prop } = this;
            if (!row[prop.children]) return;
            row[prop.children] = null;
            this.loadNode(row);
        },
        removeNode(row) {
            const { prop } = this;
            const { _parent: parent, _index: index } = row;
            parent[prop.children].splice(index, 1);
            if (parent[prop.children].length === 0) {
                parent[prop.children] = null;
                parent[prop.expand] = false;
                parent[prop.isLeaf] = true;
            }
        },
        updateRowLevel(row,level){
            const { prop } = this;
            row[prop.level] =level
            const children = row[prop.children]
            if(!children||!children.length)return
            children.forEach(item => {
                this.updateRowLevel(item,level+1)
            })
        },
        async emitMove(event){
            return new Promise((resolve, reject) => {
                this.$emit('move', { ...event,resolve, reject });
            })
        },
        async onMove(detail){
            await this.emitMove(detail);
            const { prop } = this;
            const {replaceData,targetData} = detail
            const isPeer = replaceData._parent === targetData._parent
            if(isPeer){
                const children = targetData._parent[prop.children]
                children.splice(targetData._index,1)
                children.splice(replaceData._index,0,targetData)
            }else {
                targetData._parent[prop.children].splice(targetData._index,1)
                replaceData._parent[prop.children].splice(replaceData._index,0,targetData)
                this.updateRowLevel(targetData,replaceData[prop.level])
            }
        }
    },
    mounted() {
        this.rootNode = this.data;
        if (!this.initNotLoad) this.loadNode();
    },
    render() {
        const {
            $attrs, $scopedSlots, tableData, expandProp, prop, onRow,
        } = this;
        const columnChild = {
            default:(scope)=> {
                return (
                    <div
                        class={['indent-space', { leaf: scope.row[prop.isLeaf] }]}
                        style={{ 'padding-left': `${14 * scope.row[prop.level]}px` }}
                        onClick={() => onRow(scope)}
                    >
                        {
                            !scope.row[prop.isLeaf]
                                ? <i class={[{
                                    'el-icon-caret-right': !scope.row[prop.expand],
                                    'el-icon-caret-bottom': scope.row[prop.expand],
                                }]}></i>
                                : <i
                                    class="el-icon-caret-right"
                                    style="opacity: 0"
                                />
                        }
                        <div className="node-label">
                            { scope.row[expandProp.prop] }
                        </div>
                    </div>
                );
            },
        };
        const isMove = !!this.$listeners.move;
        const vOn = isMove ? { move: this.onMove } : {};
        return (
            <el-table
                class="tree-grid"
                {...{ attrs: $attrs,on:vOn  }}
                data={tableData}
            >
                <el-table-column
                    class-name="column-expand"
                    {...{ attrs: expandProp }}
                    scopedSlots={columnChild}
                >
                </el-table-column>
                {$scopedSlots.default && $scopedSlots.default()}
            </el-table>
        );
    },
};
</script>

<style lang="scss" scoped>
.tree-grid {
    td.column-expand {
        > .cell {
            padding-left: 5px;
            .indent-space {
                @include clearfix;
                &:not(.leaf) {
                    cursor: pointer;
                }
                > [class^='el-icon-'] {
                    float: left;
                    color: #97a8be;
                    margin: 5px 5px 5px 0;
                }
                > .node-label {
                    overflow: hidden;
                }
            }
        }
    }
}
</style>
