<template>
  <div :ref="uuid"
       :class="['ipub-select ',showOptions ? 'ipub-select--open' : '',ipubClass]">
    <div @click="handleClick"
         :class="['ipub-select__value', 'ipub-select__'+mode, 'ipub-select__'+(disabled?'disabled':'')]">
      <div :class="['ipub-select__value-content']">
        <div v-if="showValue"
             class="omis">
          <template v-if="mode === 'default'">
            <Vnodes v-if="isArray(showValue)"
                    :vnodes="showValue" />
            <template v-else>{{showValue}}</template>
          </template>
          <template v-else-if="mode === 'multiple'">
            <ipub-label :style="{margin: '5px 0 5px 8px'}"
                        v-for="(item, index) in showValue"
                        :key="'specialIssue.keywords'+index"
                        cover
                        :type="showOptions?'link':'default'"
                        size="common"
                        circle>
              <Vnodes v-if="isArray(item)"
                      :vnodes="item" />
              <template v-else>{{item}}</template>
            </ipub-label>
          </template>
        </div>
        <div v-else-if="isArray(selectValue)?selectValue.length:selectValue"
             class="ipub-select__placeholder">
          <font class="main-color"
                :style="mode === 'multiple'?'line-height:40px;margin-left:12px':''">NULL</font>
        </div>
        <div v-else
             :class="['ipub-select__placeholder omis', 'ipub-select__placeholder--'+mode]">
          {{ placeholder }}
        </div>
      </div>
      <font style="font-size:10px">
        <ipub-icon @click="handleClear"
                   @click.stop
                   v-if="(clear||clearable)&&showValue&&mode==='default'"
                   class="ipub-select__icon"
                   type="iconClose" />
        <ipub-icon v-else
                   :class="'ipub-select__icon'+(showOptions?' ipub-select__icon--rotate':'')"
                   type="iconArrow" />
      </font>
    </div>

    <div class="ipub-select__warp"
         :style="style">
      <div class="ipub-select__warp__item"
           @click.stop
           v-show="showOptions">
        <div v-if="search">
          <ipub-input @input="handleSearch"
                      v-model="searchVal"
                      :clearable="true"
                      suffixIcon="iconSearch"
                      @clear="handleInputClear"
                      placeholder="Search"></ipub-input>
        </div>
        <slot>
          <ipub-select-option v-for="(item, index) in options"
                              :key="'ipub-select__warp__item'+(item[optionKey]||item)+index"
                              :value="item"
                              @select="handleSelect"
                              :optionTitle="optionTitle"
                              :optionKey="optionKey"></ipub-select-option>
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
import IpubSelectOption from './option'
import IpubInput from '../../input/src/main.vue'
import { guid, debounce } from '../../../src/utils/utils'
export default {
  name: 'IpubSelect',
  components: {
    IpubSelectOption, IpubInput,
    Vnodes: {
      functional: true,
      render: (h, ctx) => ctx.props.vnodes
    }
  },
  props: {
    value: {
      type: [String, Number, Array, Object, Boolean],
      default: null
    },
    placeholder: {
      type: String,
      default: 'Please Select'
    },
    mode: {
      type: String,
      default: 'default',
      validator (val) {
        return ['default', 'multiple'].indexOf(val) !== -1
      }
    },
    optionTitle: {
      type: String,
      default: 'name'
    },
    optionKey: {
      type: String,
      default: 'id'
    },
    options: {
      type: Array,
      default () {
        return []
      }
    },
    disabled: Boolean,
    clear: Boolean,
    clearable: Boolean,
    optionsHeight: {
      type: Number,
      default: 200
    },
    tree: Boolean,
    search: Boolean,
  },
  provide () {
    return {
      theme: this//方法一：提供祖先组件的实例
    };
  },
  inject: {
    ipubFormItem: {
      default: false
    }
  },
  watch: {
    value: {
      handler (val) {
        if (val !== this.selectValue) {
          this.selectValue = val
          this.showValue = null
        }
      },
      immediate: true
    },
    showOptions (val) {
      if (val) {
        this.$emit('focus')
      } else {
        document.removeEventListener('click', this.fun)
        document.removeEventListener('scroll', this.fun)
        if (this.dom && this.dom.$el) {
          const doms = this.dom.$el.getElementsByClassName('ipub-model__content')
          for (let item of doms) {
            item.removeEventListener('scroll', this.fun)
          }
        }
        this.$emit('blur')
      }
    }
  },
  computed: {
    ipubClass () {
      let newClass = ''
      if (this.ipubFormItem && this.ipubFormItem.validateStatus) {
        newClass += 'ipub--validateStatus '
      }
      return newClass
    }
  },
  data () {
    return {
      uuid: '',
      style: {},
      showOptions: false,
      selectValue: null,
      showValue: null,
      searchVal: '',
      dom: '',
      handleSearch: ''
    }
  },
  mounted () {
    this.uuid = guid()
    this.handleSearch = debounce(() => { this.$emit('search', this.searchVal) }, 1000)
  },
  methods: {
    getShowValue (showVal) {
      if (showVal === undefined || showVal === null) {
        this.showValue = null
        return
      }
      if (this.mode === 'multiple') {
        this.showValue = this.isArray(this.showValue) ? this.showValue : []
        this.showValue.push(showVal)
      } else {
        this.showValue = showVal
      }
    },
    handleChange (val, showVal) {
      if (this.mode === 'multiple') {
        if (!val && val !== false) {
          return
        }
        this.selectValue = this.isArray(this.selectValue) ? this.selectValue : []
        this.showValue = this.isArray(this.showValue) ? this.showValue : []
        const index = this.selectValue.indexOf(val)
        if (index >= 0) {
          this.selectValue.splice(index, 1)
        } else {
          this.selectValue.push(val)
        }
        this.showValue = []
        this.getShowValue()
      } else {
        this.selectValue = val
        this.showValue = showVal
        this.showOptions = false
      }
      this.$emit('input', this.selectValue)
      this.$emit('change', this.selectValue)
      if (this.ipubFormItem) {
        this.ipubFormItem.validate('change')
      }
    },
    handleClick () {
      if (this.disabled) {
        return
      }
      const el = this.$refs[this.uuid]
      const sty = el.getBoundingClientRect() || {}

      this.$set(this.style, 'left', sty.left + 'px')
      this.$set(this.style, 'top', sty.bottom + 'px')
      this.$set(this.style, 'width', sty.width + 'px')
      this.$set(this.style, 'max-height', this.optionsHeight + 'px')
      this.showOptions = !this.showOptions
      if (this.showOptions) {
        setTimeout(() => {
          document.addEventListener('click', this.fun)
          document.addEventListener('scroll', this.fun)

          this.dom = this.findModel(this.$parent)
          if (this.dom && this.dom.$el) {
            const doms = this.dom.$el.getElementsByClassName('ipub-model__content')

            for (let item of doms) {
              item.addEventListener('scroll', this.fun)
            }
          }
        }, 0);
      }
    },
    handleSelect (val, item) {
      this.$emit('select', item)
    },
    handleClear () {
      this.handleChange(null, null)
      this.$emit('clear')
    },
    closeSelect () {
      this.showOptions = false
    },
    findScroll () {
      this.options.forEach((item, index) => {
        if (
          this.value === (this.isObject(item) ? item[this.optionKey] : item)
        ) {
          setTimeout(() => {
            this.$refs.openOptions.scrollTop = 32 * index
          }, 0)
        }
      })
    },
    isObject (obj) {
      return Object.prototype.toString.call(obj) === '[object Object]'
    },
    isArray (obj) {
      return Object.prototype.toString.call(obj) === '[object Array]'
    },
    fun () {
      this.showOptions = false
    },
    findModel (v) {
      if (!v) {
        return
      }
      if (v.visable) {
        return v
      }
      return this.findModel(v.$parent)
    },
    handleInputClear () {
      this.searchVal = ''
      this.handleSearch()
    }
  }
}
</script>

<style lang="scss">
.ipub-select {
  position: relative;
  display: inline-block;
  font-family: $p_family;
  background: #fff;
  border-radius: 4px;
  border: 1px solid $border_color;
  transition: 0.3s all;
  box-sizing: border-box;
  width: 100%;
  .ipub-select__value {
    width: 100%;
    display: flex;
    box-sizing: border-box;
    color: $main_color;
    border: none;
    outline: none;
    line-height: 20px;
    min-height: 40px;
    padding: 10px 12px;
    font-size: 14px;
    cursor: pointer;
    .ipub-select__value-content {
      width: calc(100% - 10px);
    }
    .ipub-select__icon {
      position: absolute;
      transition: 0.3s all;
      display: inline-block;
      right: 12px;
      top: 11px;
      &.ipub-select__icon--rotate {
        transform: rotate(180deg);
      }
    }
  }
  .ipub-select__multiple {
    padding: 0;
  }
  .ipub-select__placeholder {
    color: $line_color;
    &--multiple {
      height: 40px;
      line-height: 40px;
      padding-left: 20px;
    }
  }
  .ipub-select__disabled {
    background: $disable_color;
    cursor: not-allowed;
  }
  &.ipub-select--open {
    border: 1px solid $link_color;
  }
  .ipub-select__warp {
    position: fixed;
    width: max-content;
    max-height: 0;
    border-radius: 4px;
    // transition: all 0.3s;
    box-sizing: border-box;
    z-index: 999;
    margin-top: 5px;
    overflow-y: auto;
    overflow-x: hidden;
    border: 0px solid $border_color;
    .ipub-select__warp__item {
      background: #fff;
      padding: 10px 0;
      overflow-y: auto;
      .ipub-select-option {
        font-weight: 600;
        transition: 0.3s all;
        position: relative;
        display: flex;
        align-items: center;
        padding: 5px 12px;
        cursor: pointer;
        &.default:hover,
        &.default.active {
          background: rgba($link_color, 0.2);
        }
        &.multiple:hover,
        &.default-tree:hover,
        &.default-tree.active {
          background: rgba($link_color, 0.2);
        }
        &.disabled {
          color: $default_color;
          cursor: not-allowed;
          &:hover {
            background: #fff;
          }
        }
      }
      .ipub-input {
        margin: 0 12px 10px 12px;
        width: calc(100% - 24px);
      }
    }
  }
  &.ipub-select--open {
    .ipub-select__warp {
      max-height: 200px;
      border: 1px solid $border_color;
    }
  }
  &-children {
    margin-left: 32px;
  }
}
</style>
