<script>
import Vue from 'vue'
import { Radio, Checkbox, Select } from 'ant-design-vue'

export default {
  name: 'KmListSelector',
  inheritAttrs: true,
  model: {
    prop: 'value',
    event: 'change',
  },
  props: {
    /**
     * 只读
     */
    readOnly: {
      required: true,
      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',
    },
    /**
     * 是否单选
     */
    single: {
      type: Boolean,
      default: false,
    },
    /**
     * 使用单选/复选的最大长度
     */
    checkMaxLength: {
      type: Number,
      default: 10,
    },
  },
  data() {
    return {}
  },
  computed: {
    idValue() {
      // 从object中取出id，作为实际的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转成需要的格式
      return this.allOptions.map((option) => ({
        ...option,
        label: option[this.optionLabel],
        value: option[this.optionValue],
      }))
    },
  },
  methods: {
    change(e, ...rest) {
      let objValue = []
      // 判断是单选还是多选
      if (this.single && this.computedOptions.length <= this.checkMaxLength) {
        objValue = e.target.value
      } else {
        objValue = e
      }
      if (!Array.isArray(objValue)) {
        objValue = [objValue]
      }

      objValue = objValue.map((val) => this.allOptions.find((opt) => opt[this.optionValue] === val))

      this.$emit('change', objValue, ...rest)
    },
  },
  render(h) {
    if (this.readOnly) {
      let str = ''
      let objValue = this.value

      if (Array.isArray(objValue)) {
        str = objValue.map((v) => v[this.optionLabel]).join(', ')
      } else {
        if (objValue) {
          objValue = JSON.parse(this.value)
        } else {
          objValue = []
        }
        str = objValue.map((v) => v[this.optionLabel]).join(', ')
      }
      return <span>{str}</span>
    }

    if (this.computedOptions.length === 0) {
      return h('span', '暂无数据')
    } else if (this.computedOptions.length <= this.checkMaxLength) {
      let GroupType = Checkbox.Group

      // 判断使用多选还是单选
      if (this.single) {
        GroupType = Radio.Group
      }

      return h(GroupType, {
        props: {
          value: this.single === false ? this.idValue : this.idValue[0],
        },
        attrs: {
          name: 'radioGroup',
          options: this.computedOptions,
          getPopupContainer: () => {
            return this.$parent.$el
          },
        },
        ref: 'checkoption',
        on: {
          change: this.change,
        },
      })
    } else {
      return h(Select, {
        attrs: {
          mode: this.single === false ? 'multiple' : 'default',
          value: this.idValue,
          optionLabel: this.optionLabel,
          optionValue: this.optionValue,
          options: this.computedOptions,
          showArrow: true,
          getPopupContainer: () => {
            return this.$parent.$el
          },
        },
        ref: 'select',
        on: {
          change: this.change,
        },
      })
    }
  },
}
</script>

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