<template>
  <!-- <div> -->
  <el-select
    ref="select"
    v-model="innerValue"
    :remote-method="filterMethod"
    :filterable="innerOptions.length > filterLimit"
    :remote="innerOptions.length > filterLimit"
    :size="size"
    :style="DgStyle"
    :multiple="multiple"
    :collapse-tags="collapseTags"
    :clearable="clearable"
    :placeholder="placeholder || (disabled ? '' : '请选择')"
    class="input_width_180 dg-select"
    :disabled="disabled"
    :popper-append-to-body="popperAppendToBody"
    @visible-change="handleVisibleChange"
    @change="change"
  >
    <el-option v-for="item in layoutOptions" :key="item.value" v-bind="item"> </el-option>
  </el-select>
  <!-- </div> -->
</template>

<script>
export default {
  name: 'DgSelect',
  props: {
    // eslint-disable-next-line vue/require-prop-types
    value: {
      required: true,
    }, // 接受外部v-model传入的值
    name: {
      type: [String, Array],
      default: () => '',
    },
    queryTerms: {
      type: String,
      default: () => '',
    },
    clearable: {
      type: Boolean,
      default: () => false,
    },
    multiple: {
      type: Boolean,
      default: () => false,
    },
    collapseTags: {
      type: Boolean,
      default: () => false,
    },
    DgStyle: {
      type: String,
      default: () => '',
    },
    size: {
      type: String,
      default: () => 'mini',
    },
    filterLimit: {
      type: String,
      default: () => '10',
    },
    apiCode: {
      type: String,
      default: () => '',
    },
    filterVal: {
      type: String,
      default: () => '',
    },
    fileType: {
      type: Object,
      default: () => ({ label: 'name', value: 'id', disabled: 'disabled' }),
    }, // 定义请求回来的json数据格式
    dimCode: {
      type: String,
      default: () => '',
    },
    // dimCode 可通过接口获取 options
    codeType: {
      type: String,
      default: () => '',
    },
    selectOptions: {
      type: Array,
      default: () => [],
    }, // 直接获取下拉选项数组
    selectStr: {
      type: String,
      default: () => '',
    }, // 获取进行拆分处理的字符串
    placeholder: {
      type: String,
      default: () => '',
    },
    disabled: {
      type: Boolean,
      default: () => false,
    },
    default: {
      type: Boolean,
      default: () => false,
    },
    defaultVal: {
      type: Boolean,
      default: () => false,
    },
    popperAppendToBody: {
      type: Boolean,
      default: () => true,
    },
    // 缓存
    noCache: {
      type: Boolean,
      default: () => false,
    },
    // 值转化
    valueFormat: {
      type: String,
      default: () => '',
    },
  },
  data() {
    return {
      maxOptiosNmuber: 100,
      remoteOptions: [],
      filterText: '',
    }
  },
  computed: {
    innerValue: {
      get() {
        this.updateName()
        return this.formatValue(this.value, 'in')
      },
      set(val) {
        this.$emit('input', this.formatValue(val, 'out'))
      },
    },
    // 所有的选项
    innerOptions() {
      if (this.dimCode || this.apiCode) {
        return this.remoteOptions
      }

      if (this.selectStr) {
        return this._dataTransform(this.selectStr)
      }

      if (this.selectOptions.length) {
        return this._dataTransform(this.selectOptions)
      }

      return []
    },
    innerOptionValues() {
      return this.innerOptions.map(({ value }) => value)
    },
    // 过滤后的选项
    layoutOptions() {
      if (!this.filterText) {
        return this.innerOptions.slice(0, 200)
      }

      return this.innerOptions
        .filter(({ label, value }) => {
          return (
            String(label).toLowerCase().includes(this.filterText) ||
            String(value).toLowerCase().includes(this.filterText)
          )
        })
        .slice(0, 200)
    },
  },
  watch: {
    dimCode(val) {
      if (val) {
        // 监听到变更值为空，则不更新
        this.getRemoteOptions()
      }
    },
    filterVal() {
      this.getRemoteOptions()
    },
    apiCode(val) {
      if (val) {
        // 监听到变更值为空，则不更新
        this.getRemoteOptions()
      }
    },
    queryTerms(val) {
      if (val) {
        // 监听到变更值为空，则不更新
        this.getRemoteOptions()
      }
    },
    innerOptions(val, oval) {
      if (val.length === 1 && this.default) {
        // this.svalue = val[0].value
        this.change(val[0].value, true)
      }
      if (val.length > 0 && this.defaultVal) {
        this.innerValue = val[0].value
        this.change(val[0].value, true)
      }

      this.updateName()
    },
  },
  created() {
    // 初始话下拉框的值
    if (this.disabled && !this.value && this.value !== 0) return
    this.getRemoteOptions()
  },
  methods: {
    formatValue(value, type) {
      if (this.multiple && this.valueFormat) {
        if (type === 'in') return value ? value.split(this.valueFormat) : []
        else if (type === 'out') return value.join(this.valueFormat)
      }
      return value
    },
    async getRemoteOptions() {
      const { dimCode, apiCode, filterVal, queryTerms } = this

      if (!(dimCode || apiCode)) return

      const dimKey = [dimCode, apiCode, filterVal, queryTerms].filter(Boolean).join('_')
      let state = this.$store?.state?.dimData || {}
      if (!this.noCache && state[dimKey] && state[dimKey].length) {
        this.remoteOptions = this._dataTransform(state[dimKey])
        return
      }

      let params = new URLSearchParams(queryTerms)
      params.append('command', 'init')

      if (dimCode) params.append('dimcode', dimCode)
      if (filterVal) params.append('supDimValCode', filterVal)

      const { root } = await this.$api.DgJsonStore({ apiCode: apiCode || 'sysDictMember', params: params.toString() })

      const remoteOptions = (root || []).map((item) => {
        const { ROWNAME: name, ROWCODE: id, SUPROWCODE: supId = '' } = item
        const option = { id, name, supId }

        if (this.codeType) {
          option[this.codeType] = item[this.codeType]
        }

        return option
      })

      try {
        this.$store?.commit('SAVE_DIM', {
          apiCode: apiCode,
          dimCode: dimCode,
          filterVal: filterVal,
          queryTerms: queryTerms,
          dimKey: dimKey,
          selectOptions: remoteOptions,
        })
      } catch (e) {
        console.error(`${dimCode}字典码缓存失败`)
      }

      console.log('remoteOptions: ', remoteOptions)
      this.remoteOptions = this._dataTransform(remoteOptions)
    },

    // 转换下拉框下的字段
    _dataTransform(data) {
      const _data = []
      const values = [].concat(this.value)
      if (data instanceof Array) {
        // 默认对象格式
        let fileType = this.fileType ? this.fileType : { label: 'name', value: 'id', disabled: 'disabled' }
        data.map((item, index) => {
          const flag = values.includes(item[fileType.value])
          let option = {
            label: item[fileType.label],
            value: this.codeType ? item[this.codeType] : item[fileType.value],
            disabled: item[fileType.disabled],
          }
          if (flag) {
            _data.unshift(option)
          } else {
            _data.push(option)
          }
        })
      } else if (typeof data === 'string') {
        let tmpArray = data.split(',')
        for (let i = 0; i < tmpArray.length; i++) {
          let option = tmpArray[i]
          _data.push({
            value: option.split('|')[0],
            label: option.split('|')[1],
          })
        }
      }
      return _data
    },
    change(value, flag = false) {
      this.$emit(
        'change',
        this.formatValue(value, 'out'),
        this.innerOptionValues.indexOf(value),
        this.innerOptionValues.length,
        flag
      ) // 选择的值、索引、以及值的长度
    },
    // 搜索cache
    filterMethod(query) {
      this.filterText = query.toLowerCase()
    },
    handleVisibleChange(visible) {
      if (!visible) {
        setTimeout(() => {
          this.filterText = ''
        }, 50)
      }
    },
    updateName() {
      if (this.value && this.innerOptions.length) {
        this.$emit(
          'update:name',
          []
            .concat(this.value)
            .map((v) => this.innerOptions.find(({ value }) => value === v))
            .filter(Boolean)
            .map(({ label }) => label)
            .join(this.valueFormat)
        )
      }
    },
  },
}
</script>
