
<template>
    <div class="c-tree">
        <div v-for="(item,index) in list"
             :key="index">
            <div class="c-tree-label"
                 :class="{'item-checkbox-disabled': disabledMap[index]}">
                <i v-if="loading[index] && lazyLoad"
                   :class="`icon-right-loading ${prefix}-icon-loading`"></i>
                <i v-else
                   @click="expanded(index)"
                   class="icon-right"
                   :class="{ 'icon-down': expandedMap[index] && !disabledMap[index], 'icon-opacity': !item[children] || item[children].length === 0}"></i>
                <i class="checkbox-icon icon"
                   v-if="showCheckbox"
                   :class="checkedMap[index] === 1 ? `${prefix}-icon-indeterminate` : checkedMap[index] === 2 ? `${prefix}-icon-checked`: ''"
                   @click="checked(index)"></i>
                {{item[label]}}
            </div>
            <component :ref="index"
                       class="child-node"
                       :is="`${prefix}-tree`"
                       :list="item[children]"
                       :label="label"
                       :showCheckbox="showCheckbox"
                       :children="children"
                       v-show="item[children] && item[children].length > 0 && expandedMap[index] && !disabledMap[index]"
                       :rootIndex="index"
                       :lazyLoad="lazyLoad"
                       @lazyFun="lazyFun"
                       @getCheckedNodes="getCheckedNodes"
                       :defaultCheckedNode="defaultCheckedNode"
                       :defaultDisabledNode="defaultDisabledNode"></component>
        </div>
    </div>
</template>

<script>
import { prefix, prefixMixins } from 'jdd-design/utils';
export default {
    name: `${prefix}-tree`,
    props: {
        list: Array,
        label: {
            type: String,
            default: 'label'
        },
        children: {
            type: String,
            default: 'children'
        },
        showCheckbox: {
            type: Boolean,
            default: false
        },
        rootIndex: [String, Number],
        lazyLoad: Boolean,
        defaultCheckedNode: {
            type: Array,
            default() {
                return [];
            }
        },
        defaultDisabledNode: {
            type: Array,
            default() {
                return [];
            }
        },
        defaultExpanded: Boolean
    },
    data() {
        return {
            expandedMap: {},
            // 1是半选 2是全选
            checkedMap: {},
            // disabled
            disabledMap: {},
            // loading
            loading: {}
        };
    },
    mixins: [prefixMixins],
    mounted() {
        this.init();
    },
    methods: {
        init() {
            // default checked disabled
            this.list.forEach((item, index) => {
                if (this.defaultCheckedNode.indexOf(item.id) !== -1) {
                    this.$nextTick(() => {
                        this.checked(index);
                    });
                }
                if (this.defaultDisabledNode.indexOf(item.id) !== -1) {
                    this.$nextTick(() => {
                        this.$set(this.disabledMap, index, true);
                    });
                }
                if (this.defaultExpanded) {
                    this.$nextTick(() => {
                        this.$set(this.expandedMap, index, true);
                    });
                }
            });
        },
        lazyFun(value, callback) {
            this.$emit('lazyFun', value, callback);
        },
        expanded(index) {
            if (this.disabledMap[index]) return;
            let self = this;
            this.$set(this.loading, index, true);
            if (this.lazyLoad) {
                this.$emit('lazyFun', this.list[index], function() {
                    self.loading[index] = false;
                    self.handlerExpanded(index);
                });
            } else {
                this.handlerExpanded(index);
            }
        },
        handlerExpanded(index) {
            this.$set(this.expandedMap, index, !this.expandedMap[index]);
            this.$nextTick(() => {
                if (this.$refs[index] && this.$refs[index].length > 0) {
                    this.$refs[index][0].checkedFloatDown(
                        this.checkedMap[index]
                    );
                }
            });
        },
        checked(index) {
            if (this.disabledMap[index]) return;
            if (!this.checkedMap[index] || this.checkedMap[index] === 1) {
                this.$set(this.checkedMap, index, 2);
            } else {
                this.$set(this.checkedMap, index, 0);
            }
            if (this.rootIndex !== undefined) {
                this.$parent.checkedFloatUp(
                    this.rootIndex,
                    this.getParentCheckedStatus()
                );
            }
            if (this.$refs[index] && this.$refs[index].length > 0) {
                this.$refs[index][0].checkedFloatDown(this.checkedMap[index]);
            }
            this.$emit(
                'getCheckedNodes',
                this.list[index],
                this.checkedMap[index] === 2
            );
        },
        checkedFloatUp(index, checkedValue) {
            this.$set(this.checkedMap, index, checkedValue);
            if (this.rootIndex !== undefined) {
                this.$parent.checkedFloatUp(
                    this.rootIndex,
                    this.getParentCheckedStatus()
                );
            }
        },
        checkedFloatDown(checkedValue) {
            if (checkedValue === 2 || checkedValue === 0) {
                this.list.forEach((item, index) => {
                    this.$set(this.checkedMap, index, checkedValue);
                    if (this.$refs[index] && this.$refs[index].length > 0) {
                        this.$refs[index][0].checkedFloatDown(
                            this.checkedMap[index]
                        );
                    }
                });
            }
        },
        getParentCheckedStatus() {
            let collection = Object.values(this.checkedMap).filter(
                item => item === 2
            );
            let len = this.list.length;
            switch (collection.length) {
                case len:
                    return 2;
                case 0:
                    return 0;
                default:
                    return 1;
            }
        },
        getCheckedNodes(value, isChecked) {
            this.$emit('getCheckedNodes', value, isChecked);
        }
    }
};
</script>