<template>
  <!-- @change="lovSelectChange"
            @update:renderLabel="lovSelectLabelChange" -->
  <div class="x-select">
    <el-select
      v-model="vModelValue"
      v-el-select-loadmore="loadMore"
      v-bind="$attrs"
      :remote-method="loadSearchData"
      v-on="$listeners"
      @visible-change="loadDataOnVisible"
    >
      <template v-if="!$slots.default">
        <el-option
          v-for="option in computedOptions"
          :key="option.value"
          :label="option.label"
          :value="option.value"
        >
          <x-ellipsis :label="option.label" style="max-width: 200px;" mode="origin"></x-ellipsis>
        </el-option>
      </template>
      <slot v-else></slot>
    </el-select>
  </div>
</template>
<script>
export default {
  name: 'XSelect',
  directives: {
    'el-select-loadmore': {
      bind(el, binding) {
        // 获取element-ui定义好的scroll盒子
        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
        if (!SELECTWRAP_DOM) {
          return
        }
        SELECTWRAP_DOM.addEventListener('scroll', function() {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
          if (condition) {
            binding.value()
          }
        })
      }
    }
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: [String, Array],
      default: ''
    },
    renderLabel: {
      type: String,
      default: ''
    },
    options: {
      type: Array
    },
    isRemote: {
      type: Boolean
    },
    loadRemoteData: {
      type: Function
    },
    searchRemoteData: {
      type: Function,
      default: () => () => {}
    }
  },
  data() {
    return {
      remoteOptions: [],
      loadingData: false,
      pageInfo: {
        page: 1,
        pageSize: 20
      },
      isHasOneValue: true
    }
  },
  computed: {
    vModelValue: {
      get() {
        return this.value
      },
      set(value) {
        const option = this.computedOptions.find((item) => {
          return value === item.value
        })

        this.$emit('update:renderLabel', option && option.label)
        this.$emit('update:extra', [option])
        this.$emit('change', value)
      }
    },
    computedOptions() {
      if (this.isRemote) {
        if (this.remoteOptions && this.remoteOptions.length > 0) {
          return this.remoteOptions
        } else {
          if ((this.value || this.renderLabel) && this.isHasOneValue) {
            this.isHasOneValue = false
            return [
              {
                value: this.value,
                label: this.renderLabel
              }
            ]
          } else {
            return []
          }
        }
      } else {
        if (this.options && this.options.length > 0) {
          return this.options
        } else {
          if ((this.value || this.renderLabel) && this.isHasOneValue) {
            this.isHasOneValue = false
            return [
              {
                value: this.value,
                label: this.renderLabel
              }
            ]
          } else {
            return []
          }
        }
      }
    }
  },
  watch: {},
  created() {},
  mounted() {},
  methods: {
    // 支持动态加载数据
    loadDataOnVisible($event) {
      if (this.isRemote) {
        if (!$event) {
          return
        }
        this.pageInfo = {
          page: 1,
          pageSize: 20
        }
        this.loadData('replace')
      } else {
        this.$emit('visible-change', $event)
      }
    },
    loadMore() {
      this.pageInfo.page++
      this.loadingData = true
      this.loadData()
    },
    loadData(type = 'add') {
      if (!this.isRemote) {
        return
      }
      this.loadRemoteData(type, this.pageInfo).then((resp) => {
        if (type === 'add') {
          this.remoteOptions = [...this.remoteOptions, ...resp.data]
        } else if (type === 'replace') {
          this.remoteOptions = [...resp.data]
        }
      })
    },
    loadSearchData(e) {
      this.searchRemoteData('replace', this.pageInfo, e).then((resp) => {
        this.remoteOptions = [...resp.data]
      })
    }
  }
}
</script>
