<template>
  <div v-if="props.dataLength === 0" class="nullData">
    暂无数据
  </div>
  <div v-else class="container" ref="container"
       :style="{ height: containerHeight + 'px' }">
    <div class="empty" :style="{ height: emptyHeight + 'px' }"></div>
    <ul class="list" :style="{ transform: `translateY(${translateY})` }">
      <li v-for="(item,index) in listData"
          @click="clickLi(item,index)" :key="item" class="item"
          :style="styleToLi(item,index)">
        <slot :item="item"></slot>
      </li>
    </ul>
  </div>
</template>

<script setup name="VirtualizationSelect">
import {functionDebounce} from "@/utils/debounce";

const props = defineProps({
  modelValue: {
    type: Number
  },
  data: {
    type: Array,
    default: []
  },
  value: {
    type: String,
    default: '',
  },
  dataLength: {
    type: Number,
    default: 0
  },
  localSearch: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['change', 'update:modelValue'])

const itemHeight = 34

let emptyHeight = $ref(itemHeight * props.dataLength)
let containerHeight = 300


let itemCount = Math.ceil(containerHeight / itemHeight)

const container = ref(null)
const start = ref(0)
const translateY = ref(0)

const listData = computed(() => {
  return props.data.slice(start.value, start.value + itemCount + 1)
})

const clickLi = async (item, index) => {
  await emit('update:modelValue', start.value + index);
  await emit('change', item)
}

const selectedDataSubscript = (idx) => {
  try {
    container.value.scrollTop = idx * itemHeight;
  } catch (e) {
    // console.error(e)
  }
}

const styleToLi = (item, index) => {
  if (props.value === item.value) {
    return {
      height: itemHeight + 'px',
      backgroundColor: '#409EFF',
      color: '#ffffff'
    };
  } else if (start.value + index === props.modelValue) {
    return {
      height: itemHeight + 'px',
      backgroundColor: '#909399',
      color: '#ffffff'
    }
  } else {
    return {
      height: itemHeight + 'px',
    };
  }
}

const enableScrollBar = functionDebounce(() => {
  try {
    container.value.addEventListener('scroll', e => {
      const {scrollTop} = e.target
      start.value = Math.floor(scrollTop / itemHeight)
      translateY.value = scrollTop + 'px'
    })
  } catch (e) {
  }
}, 200)


const resetData = () => {
  emptyHeight = itemHeight * props.dataLength
  containerHeight = emptyHeight > 300 ? 300 : emptyHeight
  start.value = 0
  translateY.value = 0 + 'px'
  container.value.scrollTop = 0
  itemCount = Math.ceil(containerHeight / itemHeight)
  enableScrollBar()
}

defineExpose({selectedDataSubscript, $el: container, enableScrollBar, resetData})


</script>
<style scoped lang="scss">

.nullData {
  padding: 10px 0;
  margin: 0;
  text-align: center;
  width: 100%;
  color: var(--el-text-color-secondary);
  font-size: var(--el-select-font-size);
}

.container {
  overflow: auto;
  display: flex;
  width: 100%;
  direction: rtl;


  ul {
    list-style: none;
    margin: 0;
    width: 100%;
    padding: 0;
    direction: ltr;

    .item {
      font-size: var(--el-font-size-base);
      padding: 0 32px 0 20px;
      position: relative;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: var(--el-text-color-regular);
      height: 34px;
      line-height: 34px;
      box-sizing: border-box;
      cursor: pointer;
      width: 100%;
    }

    .checked {
      background-color: #4e91f8;
      color: white;
    }

    .item:hover {
      background-color: #fac44d;
      color: white;
    }
  }
}


</style>