<template>
  <view class="comp_form_query_select" :class="[getHasShowMore(), getShowMore(), getDisabled()]">
    <view class="options">
      <template v-if="optionsList.length==0">
        <text class="no_data">暂无数据</text>
      </template>
      <template v-for="(item,index) in optionsList">
        <view class="option" :class="getOptionClass(item)" @click="chooseItem(item)">{{ item.label }} </view>
      </template>
    </view>
    <view class="showMoreBtn" v-if="hasShowMore" @click="changeShowMore">
      <template v-if="showMore">收起</template>
      <template v-else>显示更多</template>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onBeforeMount, onMounted, onUnmounted, watch, nextTick,  getCurrentInstance} from 'vue'
import { translate } from '@/common/utils/language/index'
import { getOptionsToType, filter, setMappings, getOption } from '@/common/utils/select'
import lodash from 'lodash'
import EXEC from '@/common/utils/exec'
import { onShow } from '@dcloudio/uni-app'

const instance = getCurrentInstance()
const props:any = defineProps({
  KEY: { type: String, required: true, }, // 组件字段
  data: { type: String, default: '', }, // 组件数据 v-modal
  controls: { type: Object, default: () => {}, }, // 组件配置
  show: { type: Boolean, default: false, },
})
const Value:any = computed({ //v-modal:data
  get: () => props.data[props.KEY],
  set: v => emit('update:data', v)
})
const _select:any =  computed( ()=> props.controls[props.KEY].select ) // 获取配置中select配置

const emit = defineEmits(['update:data','change:data','focus','blur', 'clear'])


// 事件 ========================================================================================
const chooseItem = (item:any) => {
  if(props.controls[props.KEY].disabled) return
  if(checkOptions.value[item.value] == undefined){
    checkOptions.value[item.value] = true
  }else{
    checkOptions.value[item.value] = !checkOptions.value[item.value]
  }
  if(!_select.value.multiple){
    for(let key in checkOptions.value){
      if(key == item.value) continue
      checkOptions.value[key] = false
    }
  }
  
  let datas:any = []
  for(let key in checkOptions.value){
    if(checkOptions.value[key]){
      datas.push(key)
    }
  }

  Value.value = datas
  emit('change:data', datas)
}
const getOptionClass = (item:any)=>{
  if(Value.value){
    return Value.value.indexOf(item.value)>=0?'active':''
  }
  else 
    return ''
}


// 选线 ========================================================================================
const checkOptions = <any>ref({})
const optionsList:any = ref([])
const timer:any = ref(null)
const setOptionsList:any = () => { // 设置选项列表到控件上；选项已处理过联动、过滤等
    clearTimeout(timer.value)
    let staticOptions:any = [] // 固定options
    if(_select.value.options){
        staticOptions = optionFilter(_select.value.options, props.controls[props.KEY])
    }    
    let apiOptions:any = []  // 接口options  
    apiOptions = optionFilter(OPTIONS.value, props.controls[props.KEY])

    // 合并固定选项和接口选项
    let newOptions = staticOptions.concat(apiOptions) 
    optionsList.value =  newOptions
    _select.value.optionsList = newOptions

    timer.value = setTimeout(()=>{
        getDefaultValue(newOptions[0], newOptions)
        IsHasShowMore()
        clearTimeout(timer.value)
    },100)
}
const debounceSetOptionsList = lodash.throttle(setOptionsList, 100, { // 获取列表防抖
    leading: true,
    trailing: true,
})
// 处理列表选项；处理联动、过滤等
const optionFilter = (options:any = [] ,controls:any) => filter(options, controls)
const OPTIONS:any = ref([])

const getTypeOptions = (Refresh = false) => { 
  /**
   *  1，调用时机：1在创建时调用、2在OPTIONS为空时或者alawayAPI为true时下拉调用、3主动点击控件刷新按钮时
   */
  let type = _select.value.type || ''
  if(!type) {
      debounceSetOptionsList()
      return
  }

  // 判断是否存在父级并且必填
  if(props.controls[props.KEY].parents?.length>0){
      for(let parentKey of props.controls[props.KEY].parents){
          if(!props.controls[props.KEY].params[parentKey] || props.controls[props.KEY].params[parentKey].length==0){
              OPTIONS.value = []
              optionsList.value = []
              return
          }
      } 
  }

  getOptionsToType({type:_select.value.type, params: props.controls[props.KEY].params, system: _select.value.system}, Refresh).then(async res => {
      OPTIONS.value = res
  }).then(()=>{
      debounceSetOptionsList()
  })
}



const getDefaultValue = (item:any, rows:any) => {
  if(_select.value.getDefault && props.controls[props.KEY]['def_value'] && props.controls[props.KEY]['def_value']!='$$SELECT()' && _select.value.getDefault != 'true'&& (!Value.value ||  Value.value.length==0)){      
      if(_select.value.multiple){ // 多选时，值的类型是数组；
          let value:any = props.controls[props.KEY]['def_value'].split(',')
          Value.value = value
          emit('change:data', value)
      }else{ // 单选时，值是字符串
          let value:any = props.controls[props.KEY]['def_value']
          Value.value = value
          emit('change:data', value)
      }
  }else if(_select.value.getDefault && item && (!Value.value ||  Value.value.length==0)){
      let value:any = item.value
      if(_select.value.multiple){ // 多选时，值的类型是数组；
          Value.value = [value]
          emit('change:data', [value])
      }else{ // 单选时，值是字符串 
          Value.value = value
          emit('change:data', value)
      }
  }
  else if(props.controls[props.KEY].required && rows.length==1 && (!Value.value ||  Value.value.length==0) ){ 
      let value:any = item.value
      Value.value = value
      emit('change:data', value)
  }
}

// 显示更多
const hasShowMore = ref(false)
const showMore = ref(false)
const getHasShowMore = () =>{
  return hasShowMore.value?'hasShowMore':''
}
const getShowMore = () =>{
  return showMore.value?'showMore':''
}
const getDisabled = () => {
  return props.controls[props.KEY].disabled?'disabled':''
}
const changeShowMore = () => {
  showMore.value = !showMore.value
}
const IsHasShowMore = () => {
    let el = uni.createSelectorQuery().in(instance).select('.options')
    el.boundingClientRect((res:any) => {
        if(res.height > 138){
          hasShowMore.value = true
        }
    }).exec()
}



// 生命周期 ========================================================================================
onBeforeMount(async() => {
})
onMounted(()=>{
  getTypeOptions(false)
})
onUnmounted(() => {
})




// 监听 ========================================================================================
// 监听联动
watch(  
  ()=>props.controls[props.KEY].params,
  (newData,oldData)=>{
    getTypeOptions(false)
  },
  { immediate: false, deep: true, }
)
watch( 
  ()=>props.data[props.KEY],
  (newData,oldData)=>{

    let dataArr = props.data[props.KEY] || []
    for(let key in checkOptions.value){
      if(dataArr.indexOf(key)>=0){
        checkOptions.value[key] = true
      }else{
        checkOptions.value[key] = false
      }
    }
  },
  { immediate: true, deep: true, }
)
watch(
  ()=>props.show,
  ()=>{
    if(props.show){
      let timer = setTimeout(()=>{
        IsHasShowMore()
        clearTimeout(timer)
      },100)
    }
  },
)

</script>

<style lang="scss">
.comp_form_query_select{
  width: 100%;
  max-height: 124px;
  overflow: hidden;
  position: relative;
  &.hasShowMore{
    max-height: 124px;
    padding-bottom: 60rpx;
  }
  &.showMore {
    max-height: none !important;
  }
  &.disabled{
    .option{
      color: #999 !important;
      
      &.active{
        color:  $primary-color;
      }
    }
  }

  >.showMoreBtn{
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: 5px;
    line-height: 60rpx;
    text-align: center;
    background: #eee;
    color: #666;
  }
  text.no_data{    
    color: #999;
    font-size: 12px;
    height: 35px;
    margin: 2px 0;
    width: 100%;
    line-height: 35px;
    text-align: center;
  }
  .options{
    display: flex;
    flex-wrap: wrap;

    .option{
      background: #eee;
      border: 2rpx solid #eee;
      color: #333;
      border-radius: 10rpx;
      line-height: 35px;
      height: 35px;
      padding: 0 10px;
      margin: 2px;
      position: relative;
      max-width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;


      &.active{
        border-color: $primary-color;
        color:  $primary-color;
        background: #fff;
      }
    }
  }
}
</style>
