<template>
    <Select
        ref="select"
        :multiple="multiple"
        class="ivu-tree-select"
        :class="classes"
        :transfer-class-name="transferClassName"
        @on-change="handleChange"
        @on-open-change="handleOpenChange"
        hideNotFound
        :filterable="filterable"
        :remote-method="remoteMethod"
        :loading="loading"
        :transfer="transfer"
    >
        <Tree
            :data="data"
            :multiple="multiple"
            @on-check-change="handleSelectNode"
            check-directly
            :show-checkbox="multiple && showCheckbox"
            :load-data="loadData"
        ></Tree>
    </Select>
</template>
<script>
    export default {
        name: 'TreeSelect',
        emits: ['on-change', 'input', 'on-open-change', 'remote-method'],
        props: {
            value: {
                type: [Array]
            },
            // Tree 的数据
            data: {
                type: Array,
                default: () => []
            },
            // multiple 模式下，value 为 Array
            multiple: {
                type: Boolean,
                default: false
            },
            filterable: {
                type: Boolean,
                default: false
            },
            loading: {
                type: Boolean,
                default: false
            },
            showCheckbox: {
                type: Boolean,
                default: false
            },
            loadData: {
                type: Function
            },
            transfer: {
                type: Boolean,
                default () {
                    return true
                }
            },
        },
        data () {
            let value = this.value

            return {
                currentValue: value,
                isChangeValueInTree: false, // 如果是点击 Tree 里改变的数据，临时置为 true，避免在 watch 的 value 中重复修改 Select 数据
            }
        },
        watch: {
            value (val) {
                if (this.isChangeValueInTree) {
                    this.isChangeValueInTree = false
                    return
                }
                let value = val
                this.currentValue = value
                this.$refs.select.reset()
                this.handleUpdateTreeNodes(this.data, true)
            },
            data () {
                if (this.isChangeValueInTree) {
                    this.isChangeValueInTree = false
                    return
                }
                this.$refs.select.reset()
                this.handleUpdateTreeNodes(this.data, true)
            }
        },
        computed: {
            valueToArray () {
                return (typeof this.currentValue === 'object') ? this.currentValue : [this.currentValue]
            },
            isCheckboxUsable () {
                return this.multiple && this.showCheckbox
            },
            transferClassName () {
                return this.transfer ? 'ivu-tree-select-transfer' : ''
            },
            classes () {
                return {
                    'ivu-tree-select-with-checkbox': this.showCheckbox
                }
            }
        },
        methods: {
            handleSelectValue (selectedNodes) {
                this.$refs.select.reset()
                this.currentValue = []
                selectedNodes.forEach(i => {
                    if (!i.children || !i.children.length) {
                        this.currentValue.push(i.value)
                        this.handleUpdateSelectValue(i.value, i.title)
                    }
                })
            },
            handleSelectNode (selectedNodes, currentNode) {
                if (this.multiple) {
                    if (selectedNodes.length) {
                        this.handleSelectValue(selectedNodes)
                    } else {
                        this.currentValue = []
                        this.$refs.select.reset()
                    }
                } else {
                    if (selectedNodes.length) {
                        const node = selectedNodes[0]
                        this.currentValue = [node.value]
                        this.handleUpdateSelectValue(node.value, node.title)
                    } else {
                        this.currentValue = []
                        this.$refs.select.reset()
                    }
                }
                this.isChangeValueInTree = true
            },
            handleUpdateTreeNodes (data, isInit = false) {
                /**
                 * 当开启 showCheckbox 时，不能选择，只能勾选，且只有在多选时支持 showCheckbox 属性
                 * */
                data.forEach(item => {
                    if (this.valueToArray.indexOf(item.value) >= 0) {
                        if (this.isCheckboxUsable) {
                            item.checked = true
                        } else {
                            item.selected = true
                        }
                        this.handleUpdateSelectValue(item.value, item.title)
                    } else {
                        if (this.isCheckboxUsable) {
                            item.checked = false
                        } else {
                            item.selected = false
                        }
                    }

                    if (item.children && item.children.length) {
                        this.handleUpdateTreeNodes(item.children)
                    }
                })

                // Select 在 onOptionClick 方法中，如果是多选，会强制将 isFocused 设置为 true，初始时会有一个蓝框
                if (isInit) this.$refs.select.isFocused = false
            },
            handleUpdateSelectValue (value, label) {
                this.$refs.select.onOptionClick({
                    value,
                    label
                })
            },
            handleChange (value) {
                this.currentValue = value
                this.$emit('input', value)

                this.$emit('on-change', value)
                this.$refs.select.reset()
                this.handleUpdateTreeNodes(this.data, true)
            },
            handleOpenChange (status) {
                this.$emit('on-open-change', status)
            },
            remoteMethod (query) {
                this.$emit('remote-method', query)
            },
        },
        mounted () {
            this.handleUpdateTreeNodes(this.data, true)
        }
    }
</script>
<style lang="less" scoped>
/deep/.ivu-select-selection{
    overflow-y: auto;
    max-height: 122px;
}
</style>
