<template lang="pug">
    DropDown.oc-select-container.vm(ref="dropdown", v-if="items",  @show="afterShow", @scroll="scroll", :disabled="disabled", :isFlex="true", @mouseenterHead="handlehoverClearIcon", @mouseleaveHead="handlehideHoverClearIcon")
        template.pr(slot="dropHead")
            select.ocFormElement(ref="select", tabindex="-1", :name="name", :required="required", :multiple="multiple", :disabled="disabled")
                option(v-for="(val, index) in selected", :value="val", :index="index", :selected="true" :key="index") {{val}}
            .oc-ipt-result.vm(:class="{ showClearAll: isShowClearAll, multipleLine: isMultipleLine }", ref="ipt", tabindex="0", :style="iptStyle", @keydown.stop="toggleAll",  @keydown.esc.stop.prevent="$refs.dropdown.hide()", :disabled="disabled", v-keynavigate:target="keyTarget", @keyup.enter="$emit('enter')")
                i.oc-select-clear-icon.fa.fa-times-circle(v-if="isShowClearAll && !disabled", tabindex="1", @click="handleClear")
                .oc-ipt-result-inner(:class="{ multipleLine: isMultipleLine }")
                    template(v-if="multiple")
                        span(v-for="item in showMultipleText") {{item.key}}
                            i(v-if="!disabled", tabindex="-1", @click="remove(item)") ×
                    .oc-ipt-result-content(v-else)
                        font.mr5 {{showSingleText}}
        
        template(slot="dropBody")
            .filter.oc-select-filter(v-if="isShowFilter")
                input.iptFilter.w.sm(tabindex="-1", type="text", placeholder="Search" @input="filterKeyword")

            .oc-select-drop-body.ocScroll(ref="itemList")
                ul(ref="ocSelectUl", :style="{height: this.visibleKeys.length  * 35 + 'px'}")
                    template(v-for="(item, index) in visibleKeys")
                        li(:value="getString(filterItemObj[item])", :index="index", :data-key="item", @click="clickLi", :class="{active: selected.indexOf(getString(filterItemObj[item])) !== -1}") {{item || filterItemObj[item]}}

</template>

<script>
    import formElement from './mixins/formElement'
    import DropDown from './dropdown'
    import keynavigate from './directives/key_navigate'
   
    export default {
        name: 'oc-select',
        mixins: [ formElement ],
        directives: { keynavigate },
        components: { DropDown },
        props: {
            default: { type: String, default: '' },
            iptStyle: null,
            items: null,
            sortType: null,
            isAll: { type: Boolean, default: false }, //是否包含please select选项 ----
            allText: { type: String, default: 'Please select' }, //please select选项显示的文本 ----
            isShowFilter: { type: Boolean, default: false },  //是否显示过滤器
            isMultipleLine: { type: Boolean, default: false },  //选项多个时，是否扩展高度，展示多行
            remote: Boolean,
            remoteMethod: Function,
        },
        
        data() {
            return {
                keyword: '',
                isShowClearAll: false,
                scrollTop: 0,    //选项过多时，只展示部分，优化性能 ---
                _timer: null,
            }
        },

        computed: {
            keyTarget(){
                return {
                    selectorFn: _ => this.$refs.dropdown.popperElm.querySelector('ul'), 
                    scrollSelectorFn: _ => this.$refs.dropdown.popperElm
                }
            },
            allCurrentText() {
                return this.allText || 'Please select';
            },
            filterItemObj() {
                if(!this.keyword) {
                    return this.itemObj;
                }
                let keyword = this.keyword.toUpperCase();
                let ret = {};
                for(var key in this.itemObj) {
                    if(key && key.toUpperCase().indexOf(keyword) !== -1) {
                        ret[key] = this.itemObj[key];
                    }
                }
                return ret;
            },
            
            allFilterKeys() {
                //将allText放在第一位
                let keys = Object.keys(this.filterItemObj);
                switch (this.sortType) { //排序
                    case 0:
                        keys = keys.sort();// 升序
                        break;
                    case 1:
                        keys = keys.sort().reverse();// 降序
                        break;
                    default:// 不排序
                        break;
                }
                if(this.isAll && !this.multiple) {
                    let allText = this.allCurrentText;
                    let index = keys.indexOf(allText);
                    if(index > -1) {
                        keys.splice(index, 1);
                        keys.splice(0, 0, allText);
                    }
                }
                return keys;
            },

            visibledStartIndex() {
                let startIndex = parseInt(this.scrollTop   / 35);
                startIndex = startIndex - 50;
                startIndex <= 0 && (startIndex = 0);
                return startIndex;
            },

            //以下参数为设置滚动条效率用的，数据太多时，滚动效率差
            visibleKeys() {
                
                return this.allFilterKeys.slice(this.visibledStartIndex, this.visibledStartIndex + 100);
            },

            allFilterValues() {
                return Object.values(this.filterItemObj).map(one => this.getString(one));
            },

            itemObj() {
                let obj = {};
                this.isAll && !this.multiple && (obj[this.allCurrentText] = '');
                if(Array.isArray(this.items)) {
                    (this.items || []).map(one => {
                        //排除undefined,null 和''，但是要保留0
                        if(one || one === 0) {
                            obj[one] = one;
                        }
                    })
                }
                else {
                    obj = Object.assign(obj, this.items);
                }
                return obj;
            },

            allValues() {
                if(!this.itemObj) {
                    return [];
                }
                return Object.values(this.itemObj).map(one => this.getString(one));
            },
            
            selected() {
                if(this.currentValue === null || this.currentValue === undefined) {
                    return [];
                }
                let selected = (this.currentValue instanceof Array)? this.currentValue : [this.currentValue];
                selected = selected.map(one => this.getString(one));
                return selected.filter(one => this.allValues.indexOf(one) !== -1);
            },
            showSingleText(){
                return this.selected.length? this.getSelectedText(this.selected[0]) : '';
                
            },
            showMultipleText(){
                return this.selected.map(item => ({key:this.getSelectedText(item),value: item}));
            },
        },

        watch: {
            items(val, oldVal) {
                if(JSON.stringify(val) != JSON.stringify(oldVal)) {
                    this.setValueToCurrent();
                }
            },
            keyword() {
                if(this.remote && this.remoteMethod) {
                    this.remoteMethod(this.keyword)
                }
            }
        },
        mounted() {
            this.setValueToCurrent();
            var slc = this.$refs.select;
            //调用oc.tools.form.fill赋值时，会触发onchange
            if(slc) {
                slc.onchange = (e, val) => {
                    let ele = e.target;
                    if(!val && ele.value) {
                        val = ele.value;
                    }
                    if(this.isEmpty(val)) {
                        this.setDefault();
                    }
                    else {
                        if(this.multiple) {
                            this.currentValue = this.filterVal(val);
                        }
                        else {
                            this.currentValue = this.getString(val);
                        }
                    }
                    //fill时的值，有可能跟最终的值不一致，使用组件中最终的值 ----
                    this.$nextTick(_ => {
                        $(ele).val(this.currentValue);
                    })
                }
            }
        },

        methods: {
            //value或者默认值设置到currentValue
            setValueToCurrent() {
                // 单选无默认空选项时，若value为空，选中第一个。
                // 单选无默认空选项时，若value不为空，且数据源存在并且数据源中没有该value，选中第一个。
                let isResetValue = !this.isAll
                    && !this.multiple
                    && this.itemObj
                    && Object.keys(this.itemObj).length
                    && !Object.values(this.itemObj).some(one=> String(this.value) === String(one));
                if (this.isEmpty(this.value) || isResetValue) {
                    this.setDefault();
                }
                else {
                    if(this.multiple) {
                        this.currentValue = this.value instanceof Array? this.value: [this.value];
                        
                        // 如果数据源是异步加载的，则有可能还没有allValues，这里会把原来的值覆盖为空
                        // this.currentValue = this.filterVal(this.currentValue.map(one => this.getString(one)));
                        this.currentValue = this.currentValue.map(one => this.getString(one))
                    }
                    else {
                        this.currentValue = this.getString(this.value);
                    }
                }
                this._fireInputEvent(this.$refs.dropdown && this.$refs.dropdown.$el? this.$refs.dropdown.$el.querySelector('.ocFormElement') : null);
            },

            //根据所有存在的值进行过滤显示 ----
            filterVal(val) {
                if(this.isEmpty(val) || !this.allValues) {
                    return [];
                }

                if(!Array.isArray(val)) {
                    val = [val];
                }
                val = val.map(one => this.getString(one));
                return val.filter(one => this.allValues.indexOf(one) !== -1);
            },

            

            afterShow() {
                this.keyword = '';
                this.$emit('focus')
            },
            
            scroll(height, scrollTop, dropBody) {
                this.scrollTop = scrollTop;
                this.$nextTick(e => {
                    $(this.$refs.ocSelectUl).css('padding-top', this.visibledStartIndex * 35 + 'px');
                })
            },

            setDefault() {
                if(this.default) {
                    this.currentValue = this.default;
                    return;
                }
                
                if(this.multiple) {
                    this.currentValue = null;
                    return;
                }
                
                if(this.isAll) {
                    this.currentValue = '';
                    return;
                }
                
                //设置第一项
                for(var key in this.itemObj) {
                    if(this.itemObj.hasOwnProperty(key)) {
                        this.currentValue = this.getString(this.itemObj[key]);
                        return;
                    }
                }

                this.currentValue = '';
            },
            
            //处理全选
            toggleAll() {
                if(!this.multiple) {
                    return false;
                }
                if(event.keyCode == 65 && (event.ctrlKey || event.metaKey)) {
                    event.preventDefault();
                    if(this.getString(this.currentValue) === this.getString(this.allFilterValues)) {
                        this.currentValue = null;
                    }
                    else {
                        this.currentValue = this.allFilterValues.slice(0);
                    }

                    return false;
                }
            },

            setSelected(val) {
                if(this.multiple) {
                    if(val instanceof Array) {
                        this.currentValue = val;
                    }
                    else if(val) {
                        this.currentValue = [val];
                    }
                    else {
                        this.currentValue = null;
                    }
                }
                else {
                    this.currentValue = val;
                }
            },

            handlehideHoverClearIcon(){
                this.isShowClearAll = false;
            },

            handlehoverClearIcon() {
                if(this.val() && (this.isAll || this.isMultiple)){
                    this.isShowClearAll = true;
                }
            }, 

            handleClear(event) {
                if(this.disabled) {
                    return;
                }
                if(this.multiple || this.isAll) {
                    this.currentValue = null;
                    this.$refs.dropdown.$el.focus();
                }
            },

            clickLi(e) {
                let li = e.currentTarget;
                let value = li.getAttribute('value');

                if(this.multiple) {
                    let index = (this.currentValue || []).indexOf(value);
                    if(index > -1) {
                        if(this.multiple || this.currentValue.length instanceof Array) {
                            this.currentValue.splice(index, 1);
                            return;
                        }
                    }
                    this.isEmpty(this.currentValue)? (this.currentValue = [value]) : this.currentValue.push(value);
                }
                else {
                    this.currentValue = value;
                    this.$refs.dropdown && this.$refs.dropdown.hide();
                }
                this.$emit('select', value)
            },
            
            //多选时才能remvoe
            remove(item) {
                if(this.disabled) {
                    return;
                }
                let index = this.currentValue? this.currentValue.indexOf(item.value) : -1;
                this.currentValue.splice(index, 1);

                this.$refs.dropdown.$el.focus();
            },

            getSelectedText(val) {
                for(var key in this.itemObj) {
                    let itemVal = this.itemObj[key];
                    let eq = typeof itemVal === 'number'? itemVal === parseInt(val) : this.getString(itemVal) === this.getString(val);
                    if(eq) {
                        return key;
                    }
                }
                return val;
            },

            filterKeyword(e) {
                e.preventDefault();
                this._timer && clearTimeout(this._timer);
                this._timer = setTimeout( t => {
                    this.keyword = e.target.value.trim().toUpperCase();
                }, 300)
            },
            
            val() {
                return this.currentValue;
            }
        },
        beforeDestroy() {
            var slc = this.$refs.select;
            //调用oc.tools.form.fill赋值时，会触发onchange
            if(slc) {
                slc.onchange = null 
            }
        }
    }
</script>

<style lang="stylus" scoped>
    select 
        display block
        position absolute
        left 0
        right 0
        top 0
        bottom 0
        z-index -1
        opacity 0
        
    .iptInner
        width 100%
        overflow hidden
    .oc-select-container
        display inline-block
        position relative
        &:focus
            outline none
        .sm 
            .oc-ipt-result
                height 28px
    
    .oc-select-filter
        padding 7px 10px
    .oc-select-drop-body
        overflow auto
        padding-bottom 20px
        min-width 120px
        color #333
        .filter
            flex 0 0 28px            
        ul
            margin 0
            max-width 40vw
            li
                white-space nowrap
                text-overflow ellipsis
                overflow hidden
                line-height 35px
                padding-left 10px
                padding-right 30px
                cursor pointer
                font-size 12px
                position relative
                font-weight 500
                &:hover
                    background-color #f0f0f0
                    white-space normal
                    word-break break-all
                &:after
                    content "へ"
                    display block
                    position absolute
                    right 12px
                    top 0
                    font-size 12px 
                    font-weight 600
                    transform scale(0.8) rotateX(-180deg) 
                    display none
                &.active
                    color #001689
                    &:after
                        display block
                &.hover, &.keynavigate-active
                    background-color #001689
                    color #fff
</style>
            
