<template>
  <div class="form-select" v-bind:class="classes" >
    <select id="select" v-model="value" :disabled="disabled">
      <template v-for="option in options">
        <optgroup v-if="_isGroup(option)" v-bind:label="option[groupLabel]">
          <option v-for="opt in option[groupValue]" :value="_getOptionValue(opt)">{{_getOptionLabel(opt)}}</option>
        </optgroup>

        <option v-else :value="_getOptionValue(option)">{{_getOptionLabel(option)}}</option>
      </template>
    </select>
    <div class="form-select__field">{{selectedText || placeholder}}</div>
  </div>
</template>

<script>
const EMPTY_STRING = '';
const SIZE_SMALL = 'small';
const CSS_SMALL = 'form-select--small';
const CSS_DISABLED = 'form-select--disabled';
const CSS_ERR = 'form-select--error';

export default {
  props: {
    bmValue: {
      type: [String, Number],
      default: EMPTY_STRING
    },
    /**
     * 下拉选项，由字符串或对象组成的数组。
     * eg：['1','2','3']，[{label: 'L1', value: '1'}, {label: 'L2', value: '2'}]
     * 分组下拉：[{label: 'group1', value: [{label: 'g1-L1', value: '1'}, {label: 'g1-L2', value: '2'}]}, {label: 'group2', value: [{label: 'g2-L1', value: '3'}, {label: 'g2-L2', value: '4'}]}]
     * 可以通过设置optLabel、optValue、groupLabel、groupValue自定义key
     * @type {Array}
     */
    options: Array,
    /**
     * 下拉组件大小，可以设置为small
     * @type {String}
     */
    size: String,
    /**
     * 是否禁用下拉组件
     * @type {Boolean}
     */
    disabled: Boolean,
    /**
     * option为对象时，label的属性名，默认为'label'
     * @type {String}
     */
    optLabel: {
      type: String,
      default: 'label'
    },
    /**
     * option为对象时，value的属性名，默认为'value'
     * @type {String}
     */
    optValue: {
      type: String,
      default: 'value'
    },
    /**
     * option为对象时，optgroup的label属性名，默认为'label'
     * @type {String}
     */
    groupLabel: {
      type: String,
      default: 'label'
    },
    /**
     * option为对象时，optgroup的子选项属性名，默认为'value'
     * @type {String}
     */
    groupValue: {
      type: String,
      default: 'value'
    },
    /**
     * 未选中任何下拉值时显示的文字，默认为'--'
     * @type {String}
     */
    placeholder: {
      type: String,
      default: '--'
    }
  },
  data: function () {
    return {
      /**
       * 下拉选中的值
       * @type {String}
       */
      value: null,
      /**
       * 下拉选中的option对象
       * @type {String||Object}
       */
      selectedOption: null,
      isErr: false
    };
  },
  created: function () {
    if (this.bmValue) {
      this.selectedOption = this._getOption(this.bmValue);
    }
  },
  methods: {
    /**
     * 获取下拉组件的值
     * @type {String||Number}
     */
    getValue: function () {
      return this._getOptionValue(this.selectedOption);
    },
    /**
     * 设置下拉值
     *
     */
    setValue: function (value) {
      this.value = value;
    },
    /**
     * 获取下拉组件的显示的文本
     * @type {String||Number}
     */
    getText: function () {
      return this._getOptionLabel(this.selectedOption);
    },
    /**
     * 获取选中的option
     * @type {String||Number||Object}
     */
    getSelected: function () {
      return this.selectedOption;
    },
    /**
     * 禁用下拉组件
     *
     */
    disable: function () {
      this.disabled = true;
    },
    /**
     * 启用下拉组件
     *
     */
    enable: function () {
      this.disabled = false;
    },
    /**
     * 重置下拉框的值
     *
     */
    reset: function () {
      this.value = this.bmValue;
    },
    /**
     * 清除选中值
     *
     */
    clear: function () {
      this.value = undefined;
    },
    /**
     * 获取option的value
     * @type {String||Number}
     */
    _getOptionValue: function (option) {
      if (option !== null && typeof option === 'object') {
        return option[this.optValue];
      }
      return option;
    },
    /**
     * 获取option的label
     * @type {String||Number}
     */
    _getOptionLabel: function (option) {
      if (option !== null && typeof option === 'object') {
        return option[this.optLabel];
      }
      return option;
    },
    _getOption: function (value) {
      var self = this;
      var currOpt;
      if (value && this.options) {
        this.options.forEach(function (option) {
          if (self._isGroup(option)) {
            option[self.groupValue].forEach(function (subOpt) {
              if (self._getOptionValue(subOpt) == value) { // eslint-disable-line
                currOpt = subOpt;
              }
            });
          } else {
            if (self._getOptionValue(option) == value) { // eslint-disable-line
              currOpt = option;
            }
          }
        });
      }

      return currOpt;
    },
    /**
     * 判断是否是分组选项
     * @type {Boolean}
     */
    _isGroup: function (optGrop) {
      return Object.prototype.toString.call(optGrop[this.groupValue]) === '[object Array]';
    }
  },
  computed: {
    classes: function () {
      var classArr = [];
      if (this.size === SIZE_SMALL) {
        classArr.push(CSS_SMALL);
      }
      if (this.disabled) {
        classArr.push(CSS_DISABLED);
      }
      if (this.isErr) {
        classArr.push(CSS_ERR);
      }
      return classArr;
    },
    selectedText: function () {
      return this._getOptionLabel(this.selectedOption) || this.placeholder || '';
    }
  },
  watch: {
    bmValue: function (newVal, oldVal) {
      this.value = newVal;
    },
    value: function (newVal, oldVal) {
      this.selectedOption = this._getOption(newVal);

      if (newVal !== oldVal) {
        this.$emit('on-change', this.value, this);
      }
    }
  }
};

</script>