<template>
    <div class="select"
         :class="{'open': visible, 'focus': hasFocusClass, 'disabled': disabled, 'select-flags': supportFlag, 'top': displayTop}"
         @click="handleSelectClick"
         v-clickoutside="handleClickOutside">

        <div class="select-title">
            <span class="select-label J-label" v-show="prefix">{{prefix}}</span>

            <div class="select-selected" v-if="!enableSelectedSlot">
                <span class="J-text" :class="[supportFlag ? 'select-flag': '', selected.flag ? 'select-flag-'+ selected.flag: '']">
                    {{selectedLabel}}
                </span>
            </div>
            <div class="select-selected" v-html="selectedLabel" v-else></div>

            <div class="select-arrow J-arrow">
                <focus-icon name="down"></focus-icon>
            </div>
        </div>
        <div class="select-list J-select-list">
            <template v-if="hasTabs">
                <div class="select-tabs-wrap" @click.stop v-if="hasTabs">
                    <ul class="select-tabs J-select-tabs">
                        <li class="select-tab J-select-tab" v-for="(tab,index) in tabs" :class="{'active': tab.visible }"
                            @click.stop="handleTabClick($event, index)">{{tab.label}}</li>
                    </ul>
                </div>
                <slot name="tabs"></slot>
            </template>
            <ul class="select-list-wrap J-select-tab-cnt" v-show="visible" v-else>
                <slot></slot>
            </ul>
        </div>
    </div>
</template>

<script>
    import FocusIcon from "focus-view/packages/icon";
    import FocusOption from "./option.vue";

    import Emitter from 'focus-view/src/mixins/emitter';
    import Clickoutside from 'focus-view/src/utils/clickoutside';
    import {getValueByPath} from 'focus-view/src/utils/util';
    import {valueEquals} from 'focus-view/src/utils/util';

    export default {
        mixins: [Emitter],

        name: "focusSelect",
        componentName: "focusSelect",
        components: {
            FocusIcon,
            FocusOption
        },

        inject: {
            focusFormItem: {
                default: ''
            }
        },
        provide() {
            return {
                'select': this
            };
        },

        directives: {Clickoutside},

        props: {
            name: String,
            id: String,
            value: {
                required: true
            },
            size: String,
            disabled: Boolean,
            placeholder: {
                type: String,
                default() {
                    return '';
                }
            },
            valueKey: {
                type: String,
                default: 'value'
            },
            prefix: String,
            supportFlag: Boolean,
            displayTop: Boolean,
            enableSelectedSlot: Boolean,
        },

        data() {
            return {
                tabs: [],
                activeTabIndex: -1,
                options: [],
                cachedOptions: [],
                selected: {},
                optionsCount: 0,
                visible: false,
                selectedLabel: '',
                hasFocusClass: false
            };
        },

        computed: {
            _elFormItemSize() {
                return (this.elFormItem || {}).elFormItemSize;
            },

            selectSize() {
                return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
            },

            hasTabs() {
                return this.$slots.tabs;
            }
        },

        watch: {
            activeTabIndex(val){
                this.tabs.forEach((tab) => {
                    tab.visible = false;
                });

                this.tabs[val].visible = true;
            },

            value(val) {
                this.setSelected();
            },

            visible(val) {
                if (!val) {
                    this.selectedLabel = '';
                    if (this.selected) {
                        if(!this.enableSelectedSlot){
                            this.selectedLabel = this.selected.currentLabel;
                        }else {
                            this.selectedLabel = this.selected.$el.querySelector(".select-opt").innerHTML;
                        }
                    }
                }
                this.$emit('visible-change', val);
            },

            options() {
                if (this.$isServer) return;

                if (!this.hasFocusClass) {
                    this.setSelected();
                }
            }
        },

        methods: {
            handleTabClick(e, index){
                this.activeTabIndex = index;
            },
            handleSelectClick(e) {
                if (!this.disabled) {
                    this.visible = !this.visible;

                    this.hasFocusClass = true;

                    if (this.visible) {
                        this.handleFocus(e);
                    }
                }
            },
            handleClickOutside() {
                this.visible = this.hasFocusClass = false;
                this.handleBlur();
            },

            emitChange(val) {
                if (!valueEquals(this.value, val)) {
                    this.$emit('change', val);
                    this.dispatch('focusFormItem', 'el.form.change', val);
                }
            },

            getOption(value) {
                let option;
                const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
                for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
                    const cachedOption = this.cachedOptions[i];
                    const isEqual = isObject
                        ? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey)
                        : cachedOption.value === value;
                    if (isEqual) {
                        option = cachedOption;
                        break;
                    }
                }
                if (option) {
                    return option;
                }else {
                    const label = !isObject ? value : '';

                    return {
                        value: value,
                        currentLabel: label
                    };
                }
            },

            setSelected() {
                let option = this.getOption(this.value);


                if(!this.enableSelectedSlot){
                    this.selectedLabel = option.currentLabel;
                }else {
                    this.selectedLabel = option.$el ? option.$el.querySelector(".select-opt").innerHTML : option.currentLabel;
                }

                this.selected = option;
            },

            handleFocus(event) {
                this.$emit('focus', event);
            },

            handleBlur(event) {
                this.$emit('blur', event);
            },


            handleOptionSelect(option) {
                const value = option ? option.value : "";

                this.$emit('input', value);
                this.emitChange(value);
                this.visible = false;
            },

            onSelectTabDestroy(index){
                if(index > -1){
                    this.activeTabIndex = 0;
                    this.tabs.splice(index, 1);
                }
            },

            onOptionDestroy(index) {
                if (index > -1) {
                    this.optionsCount--;
                    this.options.splice(index, 1);
                }
            }
        },

        created() {
            this.$on('handleOptionClick', this.handleOptionSelect);
            this.$on('setSelected', this.setSelected);
        },

        mounted() {
            if (!this.value) {
                this.handleOptionSelect(this.options[0]);
            } else {
                this.setSelected();
            }

            const noActiveTab = this.tabs.every((tab) => {
                return !tab.active;
            });

            if(this.tabs.length > 0 && noActiveTab){
                this.activeTabIndex = 0;
            }

        }
    }
</script>