<template>
  <n-options ref="options" v-model="isFocus" v-bind="{disabled, state, options, virtual, width: dropWidth, maxHeight, autoClose: false, builders, multiple}"
             @click="onOptionSelect" @select-all="onSelectAll" @on-confirm="onSubmit">
    <n-filter-refer class="n-select-filter" v-model="isFocus" v-bind="{label, state, name, values, multiple, disabled, clearable}"
                  @u-update="onReferUpdateValues"></n-filter-refer>
  </n-options>
</template>
<script>
import NOptions from '@uif/next/lib/components/options'
import NFilterRefer from '@uif/next/lib/components/filter-refer'
import {spliceOrPush, prop, isSameFormValue, deepClone} from '@uif/next/lib/utils/tools'
import {optionsSelectAll, toFormValue} from '_common/formUtils'
import {getSearchState} from '_common/SearchState'

export default {
  inheritAttrs: false,
  name: 'n-select-filter',
  components: {
    NOptions,
    NFilterRefer
  },
  props: {
    // 表单名
    name: prop.string(),
    // 表单label
    label: prop.string(),
    // 初始值 multiple 下 value 需为 Array
    value: {
      type: [Array, String, Number, Boolean],
      default: ''
    },
    // 多选
    multiple: prop.boolean(),
    // 选中的option列表
    values: prop.array(),
    // 选项
    options: prop.array(),
    // 开启虚拟滚动
    virtual: prop.boolean(),
    // 禁用
    disabled: prop.boolean(),
    // 可删除
    clearable: prop.boolean(true),
    // 搜索
    search: {
      type: [Boolean, Object],
      default: false
    },
    // 下拉宽度
    dropWidth: prop.stringNumber(),
    // 自定义渲染
    builders: prop.object(() => ({
      value: null,
      header: null,
      option: null,
      footer: null,
      empty: null
    })),
    // 最大高度
    maxHeight: prop.stringNumber(270)
  },
  data () {
    const state = getSearchState(this.search)
    state.set('isFilter', true)
    return {
      state,
      // 下拉框可见
      isFocus: false,
      nValue: null,
      scopeValue: state.toNValue(this.value, this.multiple),
      scopeValues: []
    }
  },
  watch: {
    options (options) {
      this.state.updateOptions(options)
    },
    value () {
      this.onPropValueUpdate()
    },
    nValue (nValue) {
      if (this.value !== nValue) {
        this.$emit('input', nValue)
        this.$emit('update:value', nValue)
      }
    },
    isFocus (value) {
      value ? this.onFocus() : this.onBlur()
    }
  },
  created () {
    this.state.cacheOptions(this.values)
    this.state.updateOptions(this.options)
    this.onPropValueUpdate()
  },
  methods: {
    /**
     * scope
     * **/
    // 点击选项
    onOptionSelect (option) {
      // 多选
      if (this.multiple) {
        spliceOrPush(this.scopeValue, option.value, value => isSameFormValue(value, option.value))
        this.state.updateValuesByValue(this.scopeValues, this.scopeValue)
      } else {
        this.scopeValue = option.value
        this.onSubmit()
      }
    },
    // refer 点击删除按钮
    onReferUpdateValues () {
      this.scopeValue = this.state.toNValue([], this.multiple)
      this.onSubmit()
    },
    // 反选
    onSelectAll (options, isSelected) {
      optionsSelectAll(this.scopeValue, options, isSelected)
      this.state.updateValuesByValue(this.scopeValues, this.scopeValue)
    },
    // 确定
    onSubmit () {
      if (this.state.getStringify(this.scopeValue) !== this.state.getStringify(this.nValue)) {
        this.nValue = deepClone(this.scopeValue)
        this.state.updateValuesByValue(this.values, this.nValue)
        this.$emit('u-change', this.nValue)
      }
      this.isFocus = false
    },
    // value更新 同步 scopeValue 和 scopeValues
    onPropValueUpdate () {
      if (this.state.getStringify(this.nValue) !== this.state.getStringify(this.value)) {
        this.nValue = toFormValue(this.value, this.multiple)
        this.state.updateValuesByValue(this.values, this.nValue)
      }
    },
    /**
     * nValue
     * **/
    // focus回调
    onFocus () {
      this.scopeValue = this.state.toNValue(this.nValue, this.multiple)
      this.state.updateValuesByValue(this.scopeValues, this.scopeValue)
      this.state.onFocus(this.multiple, this.scopeValues)
      this.$emit('u-focus', this)
    },
    // blur回调
    onBlur () {
      this.state.onBlur()
      this.$emit('u-blur', this)
    }
  }
}
</script>
