<template>
  <popper ref="popper" :class="classes" transition="form-drop" v-model="visible" :placement="placement" :modifiers="modifiers"
          :transfer="transfer" :disabled="disabled" :sameWidth="!dropWidth" :width="dropWidth">
    <template v-slot:reference>
      <u-input readonly :disabled="disabled" :value="label" :focus="visible" :name="name" :size="size" :border="border" :placeholder="placeholder" :ellipsis="ellipsis"></u-input>
      <u-icon type="chevron-bottom" scene="none"></u-icon>
    </template>
    <template v-slot:popper>
      <slot name="options">
        <options :options="options" :size="size" :values="values" @click="handleOptionsClick"></options>
      </slot>
    </template>
  </popper>
</template>
<script>
import UInput from '@uif/hq/src/components/input'
import Popper from '@uif/hq/src/components/popper'
import UIcon from '@uif/hq/src/components/icon'
import Options from './options.vue'
import {oneOf} from '@uif/hq/src/utils/assist'
import {toString} from '@uif/hq/src/utils/format'
import {isObject} from '@uif/hq/src/utils/object'
import {concat, map, filter} from '@uif/hq/src/utils/array'

export default {
  inheritAttrs: false,
  name: 'u-select',
  components: {
    Popper,
    UInput,
    UIcon,
    Options
  },
  props: {
    value: {
      type: [String, Number, Array],
      default: ''
    },
    // 选中的option列表
    values: {
      type: Array,
      default () {
        return []
      }
    },
    name: {
      type: String
    },
    placement: {
      type: String,
      default: 'bottom-start'
    },
    options: {
      type: Array,
      default () {
        return []
      }
    },
    multiple: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: '请选择'
    },
    size: {
      validator (value) {
        return oneOf(value, ['small', 'default', 'large'])
      },
      default: 'default'
    },
    transfer: {
      type: Boolean,
      default () {
        return false
      }
    },
    ellipsis: {
      type: Boolean,
      default: true
    },
    // 下拉宽度
    dropWidth: {
      type: [Number, String],
      default: ''
    },
    border: {
      validator (value) {
        return oneOf(value, ['none', 'line', 'rect'])
      },
      default: 'rect'
    },
    offset: {
      type: Number,
      default: -1
    }
  },
  data () {
    return {
      // 下拉框可见
      visible: false,
      // 用于对比value的参照
      propsValue: null,
      modifiers: [
        {
          name: 'offset',
          options: {
            offset: [0, this.offset]
          }
        }
      ]
    }
  },
  computed: {
    hasValue () {
      return this.values.length > 0
    },
    label () {
      return this.hasValue ? this.values[0].label : null
    },
    classes () {
      return [
        'uif-select',
        'uif-select-size-' + this.size,
        {
          'focus': this.visible,
          'available': !this.disabled,
          'disabled': this.disabled
        }
      ]
    }
  },
  watch: {
    value: {
      immediate: true,
      handler (val) {
        this.parseValue()
      }
    },
    visible (visible) {
      this.$emit(visible ? 'focus' : 'blur')
    }
  },
  mounted () {
  },
  methods: {
    // 选择事件
    handleOptionsClick (option) {
      this.setValues([option])
      const currentValue = this.syncValue()
      this.$emit('u-change', currentValue)
      this.visible = false
    },
    // 设置values
    setValues (values) {
      if (this.values.length) {
        this.values.splice(0, this.values.length)
      }
      concat(this.values, values)
    },
    // 同步values 到value
    syncValue () {
      let currentValue = this.value
      const values = map(this.values, v => v.value)
      const value = toString(values[0])
      if (this.value !== value) {
        this.$emit('input', value)
        currentValue = value
      }
      return currentValue
    },
    // 同步value 到values
    parseValue () {
      const valueStr = concat([], this.value).join('&')
      const valuesStr = map(this.values, v => v.value).join('&')
      // 如果value与本地备份不一致
      if (valueStr !== valuesStr) {
        let values = concat([], this.value)
        values = map(values, value => {
          if (isObject(value)) return value
          return this.options.find((item) => String(item.value) === String(value))
        })
        values = filter(values, item => item)
        this.setValues(values)
        this.syncValue()
      }
    }
  }
}
</script>
