<template>
    <div class="lazy-cascader" :style="{ width: width }">
        <!-- 禁用状态 -->
        <div
                v-if="disabled"
                class="el-input__inner lazy-cascader-input lazy-cascader-input-disabled"
        >
      <span v-show="placeholderVisible" class="lazy-cascader-placeholder">
        {{ placeholder }}
      </span>
            <div v-if="props.multiple" class="lazy-cascader-tags">
                <el-tag
                        v-for="(item, index) in labelArray"
                        :key="index"
                        class="lazy-cascader-tag"
                        type="info"
                        disable-transitions
                        closable
                >
                    <span> {{ item.label.join(separator) }}</span>
                </el-tag>
            </div>
            <div v-else class="lazy-cascader-label">
                <el-tooltip
                        placement="top-start"
                        :content="labelObject.label.join(separator)"
                >
                    <span>{{ labelObject.label.join(separator) }}</span>
                </el-tooltip>
            </div>
        </div>
        <!-- 禁用状态 -->
        <!-- 可选状态 -->
        <el-popover v-else ref="popover" trigger="click" placement="bottom-start">
            <!-- 搜索 -->
            <div class="lazy-cascader-search">
                <el-autocomplete
                        v-if="filterable"
                        v-model="keyword"
                        :style="{ width: searchWidth || '100%' }"
                        :popper-class="suggestionsPopperClass"
                        class="inline-input"
                        prefix-icon="el-icon-search"
                        label="name"
                        :fetch-suggestions="querySearch"
                        :trigger-on-focus="false"
                        placeholder="请输入"
                        @select="handleSelect"
                        @blur="isSearchEmpty = false"
                >
                    <template slot-scope="{ item }">
                        <div class="name" :class="isChecked(item[props.value])">
                            {{ item[props.label].join(separator) }}
                        </div>
                    </template>
                </el-autocomplete>
                <div v-show="isSearchEmpty" class="empty">{{ searchEmptyText }}</div>
            </div>
            <!-- 搜索 -->
            <!-- 级联面板 -->
            <div class="lazy-cascader-panel">
                <el-cascader-panel
                        ref="panel"
                        v-model="current"
                        :options="options"
                        :props="currentProps"
                        @change="change"
                />
            </div>
            <!-- 级联面板 -->
            <!--内容区域-->
            <div
                    slot="reference"
                    class="el-input__inner lazy-cascader-input"
                    :class="disabled ? 'lazy-cascader-input-disabled' : ''"
            >
        <span v-show="placeholderVisible" class="lazy-cascader-placeholder">
          {{ placeholder }}
        </span>
                <div v-if="props.multiple" class="lazy-cascader-tags">
                    <el-tag
                            v-for="(item, index) in labelArray"
                            :key="index"
                            class="lazy-cascader-tag"
                            type="info"
                            size="small"
                            disable-transitions
                            closable
                            @close="handleClose(item)"
                    >
                        <span> {{ item.label.join(separator) }}</span>
                    </el-tag>
                </div>
                <div v-else class="lazy-cascader-label">
                    <el-tooltip
                            placement="top-start"
                            :content="labelObject.label.join(separator)"
                    >
                        <span>{{ labelObject.label.join(separator) }}</span>
                    </el-tooltip>
                </div>
                <span
                        v-if="clearable && current.length > 0"
                        class="lazy-cascader-clear"
                        @click.stop="clearBtnClick"
                >
          <i class="el-icon-close" />
        </span>
            </div>
            <!--内容区域-->
        </el-popover>
        <!-- 可选状态 -->
    </div>
</template>
<script>
    export default {
        props: {
            value: {
                type: Array,
                default: () => {
                    return []
                }
            },
            separator: {
                type: String,
                default: '/'
            },
            placeholder: {
                type: String,
                default: '请选择'
            },

            width: {
                type: String,
                default: '400px'
            },
            filterable: Boolean,
            clearable: Boolean,
            disabled: Boolean,
            props: {
                type: Object,
                default: () => {
                    return {}
                }
            },
            suggestionsPopperClass: {
                type: String,
                default: 'suggestions-popper-class'
            },
            searchWidth: {
                type: String
            },
            searchEmptyText: {
                type: String,
                default: '暂无数据'
            }
        },
        data() {
            return {
                isSearchEmpty: false,
                keyword: '',
                options: [],
                current: [],
                labelObject: { label: [], value: [] },
                labelArray: [],
                currentProps: {
                    multiple: this.props.multiple,
                    checkStrictly: this.props.checkStrictly,
                    value: this.props.value,
                    label: this.props.label,
                    leaf: this.props.leaf,
                    lazy: true,
                    lazyLoad: this.lazyLoad
                }
            }
        },
        computed: {
            placeholderVisible() {
                if (this.current) {
                    return this.current.length == 0
                } else {
                    return true
                }
            }
        },
        watch: {
            current() {
                this.getLabelArray()
            },
            value(v) {
                this.current = v
            },
            keyword() {
                this.isSearchEmpty = false
            }
        },
        created() {
            this.initOptions()
        },
        methods: {
            // 搜索是否选中
            isChecked(value) {
                // 多选
                if (this.props.multiple) {
                    const index = this.current.findIndex(item => {
                        return item.join() == value.join()
                    })
                    if (index > -1) {
                        return 'el-link el-link--primary'
                    } else {
                        return ''
                    }
                } else {
                    if (value.join() == this.current.join()) {
                        return 'el-link el-link--primary'
                    } else {
                        return ''
                    }
                }
            },
            // 搜索
            querySearch(query, callback) {
                this.props.lazySearch(query, list => {
                    callback(list)
                    if (!list || !list.length) this.isSearchEmpty = true
                })
            },
            // 选中搜索下拉搜索项
            handleSelect(item) {
                if (this.props.multiple) {
                    const index = this.current.findIndex(obj => {
                        return obj.join() == item[this.props.value].join()
                    })
                    if (index == -1) {
                        this.$refs.panel.clearCheckedNodes()
                        this.current.push(item[this.props.value])
                        this.$emit('change', this.current)
                    }
                } else {
                    // 选中下拉选变更值
                    if (
                        this.current == null ||
                        item[this.props.value].join() !== this.current.join()
                    ) {
                        this.$refs.panel.activePath = []
                        this.current = item[this.props.value]
                        this.$emit('change', this.current)
                    }
                }
                this.keyword = ''
            },
            // 初始化数据
            async initOptions() {
                this.props.lazyLoad(0, list => {
                    this.$set(this, 'options', list)
                    if (this.props.multiple) {
                        this.current = [...this.value]
                    } else {
                        this.current = this.value
                    }
                })
            },
            async getLabelArray() {
                if (this.props.multiple) {
                    const array = []
                    for (let i = 0; i < this.current.length; i++) {
                        const obj = await this.getObject(this.current[i])
                        array.push(obj)
                    }
                    this.labelArray = array
                    this.$emit('input', this.current)
                    if (!this.disabled) {
                        this.$nextTick(() => {
                            this.$refs.popover.updatePopper()
                        })
                    }
                } else {
                    this.labelObject = await this.getObject(this.current || [])
                    this.$emit('input', this.current)
                }
            },
            /** 格式化id=>object */
            async getObject(id) {
                try {
                    let options = this.options
                    const nameArray = []
                    for (let i = 0; i < id.length; i++) {
                        const index = options.findIndex(item => {
                            return item[this.props.value] == id[i]
                        })
                        if (index < 0) {
                            continue
                        }
                        nameArray.push(options[index][this.props.label])
                        if (i < id.length - 1 && (!options[index].children.length)) {
                            const list = new Promise(resolve => {
                                this.props.lazyLoad(id[i], list => {
                                    resolve(list)
                                })
                            })
                            this.$set(options[index], 'children', await list)
                            options = options[index].children
                        } else {
                            options = options[index].children
                        }
                    }
                    return { value: id, label: nameArray }
                } catch (e) {
                    this.current = []
                    return { value: [], label: [] }
                }
            },
            // 懒加载数据
            async lazyLoad(node, resolve) {
                let current = this.current
                if (this.props.multiple) {
                    current = [...this.current]
                }
                if (node.root) {
                    resolve()
                } else if (node.data[this.props.leaf]) {
                    resolve()
                } else if (node.data.children && node.data.children.length) {
                    if (this.props.multiple) {
                        this.current = current
                    }
                    resolve()
                } else {
                    this.props.lazyLoad(node.value, list => {
                        node.data.children = list
                        if (this.props.multiple) {
                            this.current = current
                        }
                        resolve(list)
                    })
                }
            },
            // 删除多选值
            /** 删除**/
            handleClose(item) {
                const index = this.current.findIndex(obj => {
                    return obj.join() == item.value.join()
                })
                if (index > -1) {
                    this.$refs.panel.clearCheckedNodes()
                    this.current.splice(index, 1)
                    this.$emit('change', this.current)
                }
            },
            // 点击清空按钮
            clearBtnClick() {
                this.$refs.panel.clearCheckedNodes()
                this.current = []
                this.$emit('change', this.current)
            },
            change() {
                this.$emit('change', this.current)
            }
        }
    }
</script>
<style lang="stylus">
    .lazy-cascader {
        display: inline-block;
        width: 300px;
        .lazy-cascader-input {
            position: relative;
            width: 100%;
            background: #fff;
            height: auto;
            min-height: 36px;
            padding: 5px;
            line-height: 1;
            cursor: pointer;
            > .lazy-cascader-placeholder {
                padding: 0 2px;
                line-height: 28px;
                color: #999;
                font-size: 14px;
            }
            > .lazy-cascader-label {
                padding: 0 2px;
                line-height: 28px;
                color: #606266;
                font-size: 14px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            > .lazy-cascader-clear {
                position: absolute;
                right: 0;
                top: 0;
                display: inline-block;
                width: 40px;
                height: 40px;
                text-align: center;
                line-height: 40px;
            }
        }
        .lazy-cascader-input-disabled {
            background-color: #f5f7fa;
            border-color: #e4e7ed;
            color: #c0c4cc;
            cursor: not-allowed;
            > .lazy-cascader-label {
                color: #c0c4cc;
            }
            > .lazy-cascader-placeholder {
                color: #c0c4cc;
            }
        }
    }
    .lazy-cascader-tag {
        display: inline-flex;
        align-items: center;
        max-width: 100%;
        margin: 2px;
        text-overflow: ellipsis;
        background: #f0f2f5;
        > span {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        > .el-icon-close {
            -webkit-box-flex: 0;
            -ms-flex: none;
            flex: none;
            background-color: #c0c4cc;
            color: #fff;
        }
    }
    .lazy-cascader-panel {
        margin-top: 10px;
        display: inline-block;
    }
    .suggestions-popper-class {
        width: auto !important;
        min-width: 200px;
    }
    .lazy-cascader-search {
        .empty {
            width: calc(100% - 24px);
            box-sizing: border-box;
            background-color: #fff;
            color: #999;
            text-align: center;
            position: absolute;
            z-index: 999;
            padding: 12px 0;
            margin-top: 12px;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
            &:before {
                content: "";
                position: absolute;
                top: -12px;
                left: 36px;
                width: 0;
                height: 0;
                border-left: 6px solid transparent;
                border-right: 6px solid transparent;
                border-top: 6px solid transparent;
                border-bottom: 6px solid #fff;
                filter: drop-shadow(0 -1px 2px rgba(0, 0, 0, 0.02));
            }
        }
    }
</style>
