<template>
    <div
        class="el-select"
        :class="[selectSize ? 'el-select--' + selectSize : '']"
        @click.stop="toggleMenu"
        v-clickoutside="handleClose"
    >
        <!-- update author: tangdm descript: add overflow: 'hidden' -->
        <div
            class="el-select__tags"
            v-if="multiple"
            ref="tags"
            :style="{ 'max-width': inputWidth - 32 + 'px', width: '100%', overflow: 'hidden' }"
        >
            <input
                type="text"
                class="el-select__input"
                :class="[selectSize ? `is-${selectSize}` : '']"
                :disabled="selectDisabled"
                :autocomplete="autoComplete || autocomplete"
                @focus="handleFocus"
                @blur="softFocus = false"
                @click.stop
                @keyup="managePlaceholder"
                @keydown="resetInputState"
                @keydown.down.prevent="navigateOptions('next')"
                @keydown.up.prevent="navigateOptions('prev')"
                @keydown.enter.prevent="selectOption"
                @keydown.esc.stop.prevent="visible = false"
                @keydown.delete="deletePrevTag"
                @compositionstart="handleComposition"
                @compositionupdate="handleComposition"
                @compositionend="handleComposition"
                v-model="query"
                @input="debouncedQueryChange"
                v-if="filterable"
                :style="{
                    'flex-grow': '1',
                    width: inputLength / (inputWidth - 32) + '%',
                    'max-width': inputWidth - 42 + 'px'
                }"
                ref="input"
            />
        </div>
        <el-input
            ref="reference"
            v-model="selectedLabel"
            type="text"
            :placeholder="currentPlaceholder"
            :name="name"
            :id="id"
            :autocomplete="autoComplete || autocomplete"
            :size="selectSize"
            :disabled="selectDisabled"
            :readonly="readonly"
            :validate-event="false"
            :class="{ 'is-focus': visible }"
            @focus="handleFocus"
            @blur="handleBlur"
            @keyup.native="debouncedOnInputChange"
            @keydown.native.down.stop.prevent="navigateOptions('next')"
            @keydown.native.up.stop.prevent="navigateOptions('prev')"
            @keydown.native.enter.prevent="selectOption"
            @keydown.native.esc.stop.prevent="visible = false"
            @keydown.native.tab="visible = false"
            @paste.native="debouncedOnInputChange"
            @mouseenter.native="inputHovering = true"
            @mouseleave.native="inputHovering = false"
        >
            <template slot="prefix" v-if="$slots.prefix">
                <slot name="prefix"></slot>
            </template>
            <template slot="suffix">
                <i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'el-icon-' + iconClass]"></i>
                <i
                    v-if="showClose"
                    class="el-select__caret el-input__icon el-icon-circle-close"
                    @click="handleClearClick"
                ></i>
            </template>
        </el-input>
        <transition name="el-zoom-in-top" @before-enter="handleMenuEnter" @after-leave="doDestroy">
            <el-select-menu ref="popper" :append-to-body="popperAppendToBody" v-show="visible && emptyText !== false">
                <slot name="empty" v-if="$slots.empty"></slot>
                <template v-if="!loading && loadData.length == 0 && query">
                    <slot name="empty" v-if="$slots.empty"></slot>
                    <p class="el-select-dropdown__empty" v-else>暂无数据</p>
                </template>
                <dg-scrollbar
                    ref="scrollbar"
                    wrap-class="el-select-dropdown__wrap"
                    view-class="el-select-dropdown__list dg-select-dropdown__list"
                    @scroll-bottom="handleScrollToBottom"
                >
                    <slot></slot>
                </dg-scrollbar>
            </el-select-menu>
        </transition>
    </div>
</template>

<script type="text/babel">
import { Select as ElSelect } from "element-ui"
import debounce from "throttle-debounce/debounce"
import { addResizeListener } from "@uiSrcPath/utils/resize-event.js"
import { complex } from "@uiSrcPath/dg-utils/shear.js"
// import { valueEquals } from '@uiSrcPath/utils/util.js';
import _ from "lodash"

ElSelect.components.ElSelectMenu.watch["$parent.inputWidth"] = function() {
    this.minWidth = Math.max(this.$parent.$el.getBoundingClientRect().width, this.$parent.$el.clientWidth) + "px"
}

const Select = complex(ElSelect, ["created", "mounted"])

export default {
    mixins: [Select],

    props: {
        // add author: tangdm
        dragTags: Boolean,
        defaultProp: Object,
        loadData: Array
    },

    data() {
        return {
            dragStatus: false,
            tagItemLength: 0,
            debounceTime: 300,
            oldValue: ""
        }
    },

    computed: {
        scrollbarCls() {
            const { allowCreate, query, filteredOptionsCount, scrollbarClass } = this
            return [!allowCreate && query && filteredOptionsCount === 0 ? "is-empty" : "", scrollbarClass || ""].join(
                " "
            )
        },
        // 覆盖element ui - select中方法
        debounce() {
            return this.debounceTime
        }
        // oldValue() {
        //   return this.selectedLabel;
        // }
    },
    watch: {
        selectDisabled() {
            // create author:lutz describe:!multiple不渲染
            if (!this.multiple) {
                return
            }
            this.$nextTick(() => {
                this.resetInputHeight()
            })
        },

        // add author: tangdm
        selected() {
            this.$nextTick(() => {
                // 检测判断标签值是否存在
                if (this.$refs.tagContent) {
                    this.$refs.tagContent.style.transform = "translateX(0px)"
                }

                // 计算标签数量值的长度
                let count = 0
                let tagItem = this.$refs.tagItem
                if (tagItem) {
                    tagItem.forEach(item => {
                        count += item.$el.offsetWidth + 8
                    })
                }
                this.tagItemLength = count
            })
        }
    },

    methods: {
        valueEquals(a, b) {
            // see: https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
            if (a === b) return true
            if (!(a instanceof Array)) return false
            if (!(b instanceof Array)) return false
            if (a.length !== b.length) return false
            for (let i = 0; i !== a.length; ++i) {
                if (a[i] !== b[i]) return false
            }
            return true
        },
        resetInputHeight() {
            if (this.collapseTags && !this.filterable) return
            this.$nextTick(() => {
                if (!this.$refs.reference) return
                let inputChildNodes = this.$refs.reference.$el.childNodes
                let input = [].filter.call(inputChildNodes, item => item.tagName === "INPUT")[0]
                const tags = this.$refs.tags
                const sizeInMap = this.initialInputHeight || 40

                // update author: tangdm descript: 不同分辨率兼容高度问题
                // [code] input.style.height = this.selected.length === 0
                //        ? sizeInMap + 'px'
                //        : Math.max(
                //        tags ? (tags.clientHeight + (tags.clientHeight > sizeInMap ? 6 : 0)) : 0,
                //        sizeInMap
                // ) + 'px';

                input.style.height =
                    this.selected.length === 0
                        ? sizeInMap + "px"
                        : Math.max(tags ? tags.clientHeight : 0, sizeInMap) + "px"
                if (this.visible && this.emptyText !== false) {
                    this.broadcast("ElSelectDropdown", "updatePopper")
                }
            })
        },

        toggleMenu() {
            // update author: tangdm descript: 拖拽状态判断
            if (this.dragStatus) {
                this.dragStatus = false
                return false
            }

            if (!this.selectDisabled) {
                if (this.menuVisibleOnFocus) {
                    this.menuVisibleOnFocus = false
                } else {
                    this.visible = !this.visible
                }
                if (this.visible) {
                    ;(this.$refs.input || this.$refs.reference).focus()
                }
            }
        },

        resetInputWidth() {
            // update author: tangdm [code] this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width;
            // descript: element count item's width for error in layers.
            this.inputWidth = Math.max(
                this.$refs.reference.$el.getBoundingClientRect().width,
                this.$refs.reference.$el.clientWidth
            )
        },

        //  下拉触发
        handleScrollToBottom() {
            this.$emit("scroll-bottom")
        },
        handleQueryChange(val) {
            if (this.oldValue === val || this.isOnComposition) return
            this.oldValue = val
            this.$nextTick(() => {
                if (this.visible) this.broadcast("ElSelectDropdown", "updatePopper")
            })
            this.hoverIndex = -1
            if (this.multiple && this.filterable) {
                this.$nextTick(() => {
                    const length = this.$refs.input.value.length * 15 + 20
                    this.inputLength = this.collapseTags ? Math.min(50, length) : length
                    this.managePlaceholder()
                    this.resetInputHeight()
                })
            }
            if (this.remote && typeof this.remoteMethod === "function") {
                this.hoverIndex = -1
                this.remoteMethod(val)
            } else if (typeof this.filterMethod === "function") {
                this.filterMethod(val)
                this.broadcast("ElOptionGroup", "queryChange")
            } else {
                this.filteredOptionsCount = this.optionsCount
                this.broadcast("ElOption", "queryChange", val)
                this.broadcast("ElOptionGroup", "queryChange")
            }
            if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) {
                this.checkDefaultFirstOption()
            }
            this.$emit("filter-change", val)
        },
        handleClearClick(event) {
            this.$emit("clearSelect")
            this.deleteSelected(event)
        },
        // 解决因树组件展开收起后引发的样式定位问题
        updatePopper() {
            setTimeout(() => {
                this.broadcast("ElSelectDropdown", "updatePopper")
            }, 300)
        }
    },

    created() {
        this.cachedPlaceHolder = this.currentPlaceholder = this.placeholder
        if (this.multiple && !Array.isArray(this.value)) {
            this.$emit("input", [])
        }
        if (!this.multiple && Array.isArray(this.value)) {
            this.$emit("input", "")
        }

        this.debouncedOnInputChange = debounce(this.debounce, () => {
            this.onInputChange()
        })

        this.debouncedQueryChange = debounce(this.debounce, e => {
            this.handleQueryChange(e.target.value)
        })

        this.$on("handleOptionClick", this.handleOptionSelect)
        this.$on("setSelected", this.setSelected)
    },

    mounted() {
        if (this.multiple && Array.isArray(this.value) && this.value.length > 0) {
            this.currentPlaceholder = ""
        }
        addResizeListener(this.$el, this.handleResize)

        const reference = this.$refs.reference
        if (reference && reference.$el) {
            const sizeMap = {
                medium: 36,
                small: 32,
                mini: 28
            }
            const input = reference.$el.querySelector("input")

            // add author: tangdm descript: 增加分辨率识别
            const clientBodyWidth = document.body.clientWidth
            const autoFixedHeight = clientBodyWidth < 1366 ? 24 : clientBodyWidth < 1681 ? 28 : 32

            // update author: tangdm [code] this.initialInputHeight = input.getBoundingClientRect().height || sizeMap[this.selectSize];
            this.initialInputHeight = sizeMap[this.selectSize] || autoFixedHeight
        }
        if (this.remote && this.multiple) {
            this.resetInputHeight()
        }
        this.$nextTick(() => {
            if (reference && reference.$el) {
                // update author: tangdm [code] this.inputWidth = reference.$el.getBoundingClientRect().width;
                this.inputWidth = Math.max(reference.$el.getBoundingClientRect().width, reference.$el.clientWidth)
            }
        })
        this.setSelected()
    }
}
</script>
