<template>
    <el-select
        ref="selectRef"
        v-model="model"
        clearable
        filterable
        :collapse-tags="row.collapseTags"
        :value-key="row.optionsValue || 'value'"
        :size="row.size"
        :placeholder="$t(row.placeholder?.() || 'pleaseSelect')"
        :filter-method="fuzzyMatching"
        :multiple="row.multiple"
        :no-data-text="$t(row.noDataText || 'noData')"
        :teleported="row.teleported === undefined ? true : row.teleported"
        :disabled="row.disabled?.(modelData)"
        :loading="row.loading?.()"
        @visible-change="visibleChanges"
        @change="changes"
    >
        <el-option
            v-for="(item, itemIndex) in result.list.slice((currentPage-1)*pageSize,currentPage*pageSize)"
            :key="item[row.optionsValue || 'value']"
            :label="row.i18n ? getLabel(item) + '' : $t(getLabel(item) + '')"
            :value="getValue(item)"
        />
        <div
            class="button-footer"
            @click.stop
        >
            <div v-if="row.multiple">
                <el-button
                    type="text"
                    size="mini"
                    @click="selectAll"
                >
                    {{ $t('selectAll') }}
                </el-button>
                <el-button
                    type="text"
                    size="mini"
                    @click="clearAll"
                >
                    {{ $t('cancel') }}
                </el-button>
            </div>
            <el-pagination
                small
                :page-size="pageSize"
                :page-sizes="[10, 15]"
                :current-page="currentPage"
                layout="total, prev, pager, next, jumper"
                :total="result.list.length"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
            />
        </div>
    </el-select>
</template>
<script lang="ts">
import { defineComponent, ref, PropType, reactive, nextTick } from 'vue'
import { isPromise, ObjectInterface } from '../../../script/index'
import useModel from '../../../script/help/useModel'
import { listInterface, SelectInterface } from './index'
export default defineComponent({
    props: {
        totalIndex: Number,
        addIndex: {
            type: [Number, String],
            default: () => ''
        },
        row: {
            type: Object as PropType<SelectInterface>,
            default: () => {}
        },
        modelData: {
            type: Object as PropType<ObjectInterface>,
            default: () => {}
        }
    },
    setup (props) {
        const { modelData, row } = props
        const selectRef = ref()
        const pageSize = ref<number>(10)
        const currentPage = ref<number>(1)
        const timer = ref<number>(0)
        let result = reactive<listInterface>({ list: [] })
        let options = reactive<listInterface>({ list: [] })
        const model = useModel(modelData, row.model, row.deepData, props.addIndex)
        // watch(() => model, (val) => {
        // }, { deep: true })
        const getLabel = (item: ObjectInterface ): string | number => {
            return row.optionsLabel ? item[row.optionsLabel] : item.label
        }
        const getValue = (item: ObjectInterface): string | number | boolean | object => {
            return row.valueItem ? item : row.optionsValue ? item[row.optionsValue] : item.value
        }
        const fuzzyMatching = (query: string): void | string => {
            clearTimeout(timer.value)
            currentPage.value = 1
            result.list = []
            if (query === '') {
                result.list = options.list
                return
            }
            timer.value = window.setTimeout(() => {
                let reg = new RegExp(query, 'gim')
                result.list = options.list.filter(item => {
                    let str: string = getLabel(item) as string
                    return str.match(reg)
                })
            }, 500)
        }
        const handleSizeChange = (val: number): void => {
            pageSize.value = val
        }
        const selectAll = (): void => {
            let res =  options.list.map(item => {
                return getValue(item)
            })
            model.value = res
            changes()
        }
        const clearAll = (): void => {
            model.value = []
            changes()
        }
        const handleCurrentChange = (val: number): void => {
            currentPage.value = val
        }
        const getSelectValue = (value: any): ObjectInterface[] => { // 获取选中的值
            let valueList = value instanceof Array ? value : [value]
            let key = row.optionsValue || 'value'
            return options.list.filter(option => valueList.includes(option[key]))
        }
        const changes = (value?:any): void => {
            let item = row.valueItem ? value : getSelectValue(model.value)
            row.methods?.(model.value, row.multiple ? item : item[0], props.addIndex, props.totalIndex)
        }
        const visibleChanges = (isDropDown: boolean): void => {
            if (isDropDown) {
                nextTick(() => {
                    selectRef.value.focus()
                })
            } else {
                nextTick(() => {
                    selectRef.value.blur()
                })
            }
            row.visibleChanges?.(isDropDown, model, modelData, row)
            if (isDropDown) {
                options.list = row.options(props.addIndex, props.totalIndex, modelData)
                if (isPromise(options.list)) {
                    options.list.then((res: any[]) => {
                        options.list = res
                    })
                }
                result.list = options.list || []
            }
        }
        const getTargetPage = (): void => {
            currentPage.value = 1
            if (model.value !== '') {
                for (let [index, item] of result.list.entries()) {
                    if (model.value === getValue(item)) {
                        currentPage.value = Math.ceil((index + 1) / pageSize.value)
                        break
                    }
                }
            }
        }
        result.list = row.options(props.addIndex, props.totalIndex)
        getTargetPage()
        return {
            pageSize,
            currentPage,
            result,
            fuzzyMatching,
            handleSizeChange,
            selectAll,
            clearAll,
            handleCurrentChange,
            changes,
            visibleChanges,
            getLabel,
            getValue,
            selectRef,
            model
        }
    }
})
</script>
<style lang="scss" scoped>
.button-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 10px;
}
.el-select {
    width: 100%;
}

:deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
}

.el-pagination {
    border-top: 1px solid var(--border-color);
    text-align: right;
    padding: 5px 10px;

    :deep(.el-input__suffix) {
        top: 2px;
    }
}

:deep(.el-input--mini .el-input__inner) {
    height: 22px;
    line-height: 20px;
}
</style>
