<script>
// a-select的value不支持object，这里处理这种情况
import Vue from 'vue'
import { Select } from 'ant-design-vue'
import processArrayInStr from '@/common/components/sd-form/process-array-in-str'

/**
 * 与a-select类似，但是value值可以是object
 * @displayName SdSelect 下拉框
 */
export default {
  name: 'SdSelect',
  inheritAttrs: false,
  model: {
    prop: 'value',
    event: 'change',
  },

  props: {
    /**
     * 只读
     */
    readOnly: {
      type: Boolean,
      default: false,
    },
    /**
     * 已选中的值
     */
    value: {
      type: [Array, String],
      default: undefined,
    },
    /**
     * 备选项列表
     */
    options: {
      type: Array,
      required: true,
    },
    /**
     * 备选项label字段名
     */
    optionLabel: {
      type: String,
      default: 'name',
    },
    /**
     * 备选项value字段名
     */
    optionValue: {
      type: String,
      default: 'id',
    },
  },
  data() {
    return {}
  },
  computed: {
    idValue() {
      // 从object中取出id，作为a-select的value
      if (typeof this.value === 'undefined' || this.value === null) return
      return Array.isArray(this.value)
        ? this.value
            .filter((v) => {
              const id = v[this.optionValue]
              if (typeof id === 'undefined') {
                Vue.util.warn(
                  `指定的 optionValue:“${this.optionValue}” 在 value:“${JSON.stringify(
                    v
                  )}” 中未找到`,
                  this
                )
                return false
              }

              return true
            })
            .map((v) => v[this.optionValue])
        : []
    },
    allOptions() {
      let objValue = this.value
      if (!objValue || !Array.isArray(objValue)) {
        objValue = []
      }
      // 找到那些已经在value中，但是options里面没有的值，也加入到options中
      const optionsInValue = []
      objValue.forEach((val) => {
        if (!this.options.find((opt) => opt[this.optionValue] === val[this.optionValue]))
          optionsInValue.push(val)
      })
      return optionsInValue.concat(this.options)
    },
    computedOptions() {
      // 把option转成a-select格式
      return this.allOptions.map((option) => ({
        ...option,
        label: option[this.optionLabel],
        value: option[this.optionValue],
      }))
    },
    listeners() {
      const { change, ...listeners } = this.$listeners
      return listeners
    },
  },
  created() {
    // 自动处理 parseBackendValue 等
    const item = this.SdFormItemContext
    if (!item || Array.isArray(item.name)) return
    this.SdFormContext.fieldOptions[item.name] = {
      ...this.SdFormContext.fieldOptions[item.name],
      ...processArrayInStr,
      dataType: 'array',
    }
    this.SdFormContext.fieldOptions = { ...this.SdFormContext.fieldOptions }
    if (typeof this.SdFormContext.model[item.name] === 'string') {
      // 只有model的值是字符串时，才走parseBackendValue。如果已经是数组，表明已经处理过了
      this.SdFormContext.parseBackendValue(item.name)
    }
  },
  inject: {
    SdFormContext: { default: () => ({}) },
    SdFormItemContext: { default: () => undefined },
  },
  methods: {
    blur() {
      this.$refs.select.blur()
    },
    change(value, ...rest) {
      // 从a-select取出id值，在options中查找到对应的object，作为值返回
      let objValue = value
      if (objValue === null || objValue === undefined) {
        objValue = []
      } else if (!Array.isArray(objValue)) {
        objValue = [objValue]
      }

      objValue = objValue.map((val) => this.allOptions.find((opt) => opt[this.optionValue] === val))
      /**
       * 选中 option，或 input 的 value 变化（combobox 模式下）时，调用此函数
       * @property {Array|Object} value 已选的值
       */
      this.$emit('change', objValue, ...rest)
    },
  },
  render() {
    if (this.readOnly) {
      let str = ''
      if (Array.isArray(this.value)) {
        str = this.value.map((v) => v[this.optionLabel]).join(', ')
      }
      return <span>{str}</span>
    }

    return (
      <Select
        ref={'select'}
        attrs={{
          'allow-clear': this.value?.length > 1, // 放前面，可以被传过来的属性覆盖
          ...this.$attrs,
          value: this.idValue,
          optionFilterProp: 'children',
          options: this.computedOptions,
        }}
        on={{
          change: this.change,
          ...this.listeners,
        }}
      />
    )
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
</style>

<docs>
```vue
<template>
  <div>
    <p>单选
    <sd-select :options="options" v-model="val"/></p>
    <p>v-model的值：{{val}}</p>
    <p>多选
    <sd-select :options="options" v-model="valueMultiple" mode="multiple"/></p>
    <p>v-model的值：{{valueMultiple}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 如果是常规的a-select，val应该是1
      val:[{"id":1,"name":"张三"}],
      valueMultiple:[{"id":2,"name":"李四"}],
      options:[{
        id:1,
        name:'张三',
        title:'悬停提示信息',
      },{
        id:2,
        name:'李四',
      },{
        id:3,
        name:'王五',
      },]
    };
  },
}
</script>
```
</docs>
