<!-- eslint-disable vue/v-on-event-hyphenation -->
<template>
  <div ref="divComInputFilter">
    <a-input
      ref="aComInputFilter"
      v-if="!ifTextarea"
      AutoComplete="off"
      :autofocus="autofocus"
      v-model:value="filterValue"
      @keydown="onKeyDownDelete"
      @keyup="onKeyUpDelete"
      @pressEnter="pressEnter"
      @focus="foucus" />
    <a-textarea
      ref="aComInputFilter"
      class="input-textarea-span"
      v-else
      AutoComplete="off"
      :autofocus="autofocus"
      v-model:value="filterValue"
      @keydown="onKeyDownDelete"
      @keyup="onKeyUpDelete"
      @pressEnter="pressEnter"
      @focus="foucus" />
    <span style="position: absolute; top: -9999px; left: 0px; white-space: pre; font-size: 12px">
      >
      {{ filterValue }}
    </span>
    <!-- 单选选项 -->
    <div v-if="isOptionsShow" class="show-options-content">
      <div class="ns-input-filter-list" v-if="singleSearchOptions.length > 0">
        <ul class="options-list-text" ref="showOptionsContent">
          <p v-if="emptyLength > 0" class="is-disabled"> 是否是空值 </p>
          <li
            @click.stop="chooseOption(item)"
            v-for="(item, index) in singleSearchOptions"
            :key="index"
            :style="index < emptyLength ? '' : 'display:none'"
            :class="[item.chooseed ? 'choose-li' : '']">
            {{ item.label }}
          </li>
          <p v-if="emptyLength > 0" class="is-disabled"> 按值筛选 </p>
          <li
            @click.stop="chooseOption(item)"
            v-for="(item, index) in singleSearchOptions"
            :key="index"
            :style="index >= emptyLength ? '' : 'display:none'"
            :class="[item.chooseed ? 'choose-li' : '']">
            {{ item.label }}
          </li>
        </ul>
      </div>
      <div class="ns-input-filter-list" v-else>
        <ul class="options-list-text">
          <p class="is-disabled"> 暂无数据 </p>
        </ul>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
  import {
    defineComponent,
    ref,
    computed,
    toRaw,
    watch,
    onMounted,
    onBeforeUnmount,
    nextTick,
  } from 'vue';
  import { http } from '/nerv-lib/util';
  import { onClickOutside } from '@vueuse/core';
  import * as utils from './input-filter-util';

  export default defineComponent({
    name: 'NsInputFilterSingleSearch',
    props: {
      value: String,
      chooseItem: {
        type: Object,
        default: () => {},
      },
      spanIndex: Number,
      autofocus: Boolean,
      optionsValue: Number | String,
      fileValue: Array,
    },
    emits: ['change', 'chooseOptions', 'keydown', 'pressEnter'],
    setup(props, ctx) {
      console.log('NsInputFilterSingleSearch');
      console.log(props);
      const focusObj = ref({
        focus: true,
      });
      const aComInputFilter = ref(null);
      //span点击 input为textArea
      // const ifTextarea = ref(typeof props.spanIndex != 'undefined' ? true : false);
      const ifTextarea = ref(false);
      onMounted(() => {
        if (props.autofocus) {
          aComInputFilter.value != null
            ? aComInputFilter.value.input.focus({
                cursor: 'start', // 聚焦在文本的开始位置
              })
            : '';
        }
      });
      const singleSearchOptions = ref([]);
      const isOptionsShow = ref(false);
      let isEmptyItem = ref(props.chooseItem);
      let filterValue = ref(toRaw(props.value));
      const optionInfo = ref();
      const page = ref(0);
      const emptyLength = ref(0);
      /**
       * 初始化选项
       */
      initOptions();
      function initOptions() {
        if (isEmptyItem.value.showEmptyOption.length > 0) {
          emptyLength.value = isEmptyItem.value.showEmptyOption.length;
          let array = JSON.stringify(isEmptyItem.value.showEmptyOption);
          singleSearchOptions.value = JSON.parse(array);
        } else {
          emptyLength.value = 0;
        }
        if (
          typeof props.chooseItem.item.componentProps.interfaceGet == 'undefined' ||
          !props.chooseItem.item.componentProps.interfaceGet
        ) {
          singleSearchOptions.value = singleSearchOptions.value.concat(
            props.chooseItem.item.componentProps.options,
          );
          if (typeof props.optionsValue != 'undefined') {
            pushCooseedOption();
          }
          isOptionsShow.value = true;
        } else {
          interfaceGetOptions();
        }
      }

      /**
       * 接口获取数据
       */
      function interfaceGetOptions() {
        // debugger;
        const requestMethod = props.chooseItem.item.componentProps.requestMethod;
        const params =
          typeof props.chooseItem.item.componentProps.params != 'undefined'
            ? props.chooseItem.item.componentProps.params
            : {};
        const api =
          typeof props.chooseItem.item.componentProps.api != 'undefined'
            ? props.chooseItem.item.componentProps.api
            : '';
        const config = {
          // headers: {
          //   'Content-Type': 'multipart/form-data',
          // },
        };
        const path = props.chooseItem.item.componentProps.labelFieldPath.split('[*]')[0].slice(1);
        const labelField = props.chooseItem.item.componentProps.labelFieldPath
          .split('[*]')[1]
          .slice(1);
        const value = props.chooseItem.item.componentProps.valueFieldPath.split('[*]')[1].slice(1);
        const method = requestMethod;
        let info = {
          params,
          api,
          config,
          path,
          labelField,
          value,
          method,
        };
        optionInfo.value = info;
        handleParams();
        switch (requestMethod) {
          case 'GET':
            optionInfo.value.method = 'get';
            break;
          case 'POST':
            optionInfo.value.method = 'post';
            break;
          default:
            break;
        }
        interfaceHttp(undefined).then(
          (value) => {
            // console.log(value);
            handleScroll();
          },
          (reason) => {
            // console.log(reason);
          },
        );
      }

      /**
       * 处理参数
       */
      function handleParams() {
        let api = optionInfo.value.api;
        if (api.indexOf('http') != -1) {
          let i = 1;
          while (i <= 4) {
            let delIndex = api.indexOf('/');
            api = api.slice(delIndex == 0 ? delIndex + 1 : delIndex);
            i++;
          }
          optionInfo.value.api = api;
        }
      }

      //是否需要分页
      const isPaging = ref(true);

      /**
       *
       */
      function interfaceHttp(params: undefined | Object) {
        return new Promise(function (resolve, reject) {
          let api = optionInfo.value.api;
          optionInfo.value.page = page.value;
          if (typeof params != 'undefined') {
            // optionInfo.value.page = page.value;
            api = optionInfo.value.api;
          }
          let filterParams = {};
          if (props.chooseItem.item.componentProps.getParams) {
            //console.log('filterParams', params);
            let getParams = props.chooseItem.item.componentProps.getParams;
            let fileValue = props.fileValue;
            if (!props.fileValue && sessionStorage.getItem('filterArray')) {
              fileValue = JSON.parse(sessionStorage.getItem('filterArray'));
            }
            for (let i in getParams) {
              filterParams[i] = fileValue
                ?.filter((item) => {
                  return item.name == getParams[i];
                })
                ?.map((item) => {
                  return item.value;
                })
                .join('');
            }
          }
          //console.log('filterParams', filterParams);
          http[optionInfo.value.method](
            api,
            {
              ...filterParams,
              // optionInfo.value.params
              page: optionInfo.value.page,
            },
            optionInfo.value.config,
          )
            .then((res: { [x: string]: any[] }) => {
              if (
                res[optionInfo.value.path].length > 0 &&
                (typeof res.page != 'undefined' ? res.page == page.value : true)
              ) {
                typeof res.page == 'undefined' ? (isPaging.value = false) : '';
                res[optionInfo.value.path].forEach((elem: { [x: string]: any }, index: any) => {
                  let item = {
                    value: elem[optionInfo.value.value],
                    label: elem[optionInfo.value.labelField],
                  };
                  singleSearchOptions.value.push(item);
                });
                if (typeof props.optionsValue != 'undefined') {
                  pushCooseedOption();
                }
              } else if (page.value > 0) {
                page.value -= 1;
              }
              isOptionsShow.value = true;
              resolve('success');
            })
            .catch((err: any) => {
              reject('fail');
              isOptionsShow.value = true;
            });
        });
      }

      /**
       * 数据回显
       */
      function pushCooseedOption() {
        let checkedOptions = props.optionsValue;
        singleSearchOptions.value.forEach((elem, index) => {
          elem.value == checkedOptions ? (elem.chooseed = true) : (elem.chooseed = false);
        });
      }

      /**
       * 计算input宽度
       * 选项div展示位置
       */
      let inputWidth = computed(() => {
        if (typeof filterValue.value == 'undefined') {
          return 8 + 'px';
        }
        return DataLength(filterValue.value) + 'px';
      });
      const DataLength = (fData: string) => {
        return utils.DataLength(fData);
      };
      let divLeft = computed(() => {
        if (typeof filterValue.value == 'undefined') {
          return 8 + 'px';
        }
        return DataLength(filterValue.value.split('：')[0]) + 'px';
      });

      //回车
      function pressEnter() {
        if (
          props.value.split(':')[0] == filterValue.value.split('：')[0] &&
          filterValue.value.indexOf('：') != -1
        ) {
          let ifChooseed = singleSearchOptions.value.filter(function (item) {
            return item.chooseed == true;
          });
          if (ifChooseed.length > 0) {
            let spanIndex = typeof props.spanIndex != 'undefined' ? props.spanIndex : -1;
            ctx.emit('chooseOptions', filterValue.value, ifChooseed[0], spanIndex);
          } else {
            filterValue.value = filterValue.value.split('：')[0] + '：';
            isOptionsShow.value = true;
          }
          return;
        }
        ctx.emit('pressEnter', filterValue.value, props.spanIndex, true, true);
      }

      //删除
      function onKeyDownDelete(event: { key: string }) {
        if (event.key == 'Backspace') {
          if (typeof filterValue.value != 'undefined' && filterValue.value != '') {
            return;
          }
          ctx.emit('keydown', props.spanIndex);
        }
      }

      function onKeyUpDelete(event: { key: string }) {
        if (event.key == 'Backspace') {
          if (typeof filterValue.value != 'undefined' && filterValue.value != '') {
            if (filterValue.value.indexOf('：') != -1) {
              let value = filterValue.value.split('：')[1];
              singleSearchOptions.value.forEach((elem, index) => {
                elem.label == value ? (elem.chooseed = true) : (elem.chooseed = false);
              });
            } else {
              isOptionsShow.value = false;
            }
            return;
          }
        }
      }

      /**
       * 空值与不为空值选中
       */
      function chooseOption(item: any) {
        isOptionsShow.value = false;
        let spanIndex = typeof props.spanIndex != 'undefined' ? props.spanIndex : -1;
        ctx.emit('chooseOptions', filterValue.value, item, spanIndex);
      }

      /**
       * 关闭展示选项区域
       */
      function closeDiv() {
        isOptionsShow.value = false;
      }

      /**
       * 打开展示选项区域
       */
      function openDiv() {
        isOptionsShow.value = true;
      }

      //需要监听的数据
      watch(
        () => filterValue.value,
        (newValue, oldValue) => {
          let spanIndex = typeof props.spanIndex != 'undefined' ? props.spanIndex : -1;
          ctx.emit('change', newValue, spanIndex);
          let value = newValue.split('：')[1];
          singleSearchOptions.value.forEach((item) => {
            if (item.label == value) {
              item.chooseed = true;
            } else {
              item.chooseed = false;
            }
          });
        },
      );

      function foucus() {
        if (singleSearchOptions.value.length <= 0) return;
        isOptionsShow.value = true;
      }

      function checkDefault() {
        let value = filterValue.value.split('：')[1];
        singleSearchOptions.value.forEach((item) => {
          if (item.label == value) {
            item.chooseed = true;
          } else {
            item.chooseed = false;
          }
        });
        pressEnter();
      }

      const divComInputFilter = ref(null);
      /**
       * 选中div区域外
       */
      onClickOutside(divComInputFilter, () => {
        isOptionsShow.value = false;
      });

      //监听滚动代码区域 showOptionsContent
      const showOptionsContent = ref();
      let oldScrollTop = 0; // 记录上一次滚动结束后的滚动距离
      const scrollTop = ref<number>(0); // 记录当前的滚动距离
      const scrollFixedStatus = ref<boolean>(true);
      function handleScroll() {
        nextTick(() => {
          showOptionsContent.value.addEventListener('scroll', () => {
            //获取dom滚动距离
            scrollTop.value = showOptionsContent.value.scrollTop;

            //获取可视区高度
            const offsetHeight = showOptionsContent.value.offsetHeight;

            //获取滚动条总高度
            const scrollHeight = showOptionsContent.value.scrollHeight;

            //console.log('scrollTop.value', scrollTop.value, scrollHeight, offsetHeight);

            if (scrollTop.value + offsetHeight >= scrollHeight) {
              // 把距离顶部的距离加上可视区域的高度 等于或者大于滚动条的总高度就是到达底部
              // console.log('已滚动到底部');
              if (isPaging.value) {
                page.value++;
                interfaceHttp('bottom');
              }
            }
          });
        });
      }
      onBeforeUnmount(() => {
        if (typeof showOptionsContent.value != 'undefined' && showOptionsContent.value != null) {
          showOptionsContent.value.removeEventListener('scroll', () => {}); // 离开当前组件别忘记移除事件监听
        }
      });

      watch(
        () => scrollTop.value,

        (newValue, oldValue) => {
          setTimeout(() => {
            if (newValue === window.scrollY) {
              // 延时执行后当newValue等于window.scrollY，代表滚动结束
              // console.log('滚动结束');
              oldScrollTop = newValue; // 每次滚动结束后都要给oldScrollTop赋值
              // scrollFixedStatus.value = true;
            }
          }, 20); // 必须使用延时器，否则每次newValue和window.scrollY都相等，无法判断，20ms刚好大于watch的侦听周期，故延时20ms
          if (oldScrollTop === oldValue) {
            scrollFixedStatus.value = false;
            // 每次滚动开始时oldScrollTop与oldValue相等
            // console.log('滚动开始');
          }
        },
      );

      // watch(
      //   () => props.optionsValue,
      //   (newValue) => {
      //   },
      //   {
      //     immediate: true,
      //   },
      // );

      function changeDefalutValue(value) {
        filterValue.value = value.label + '：' + value.value;
        let filterSpData = filterValue.value.split('：')[1];
        singleSearchOptions.value.forEach((item) => {
          if (item.label == filterSpData) {
            item.chooseed = true;
          } else {
            item.chooseed = false;
          }
        });
        let ifChooseed = singleSearchOptions.value.filter(function (item) {
          return item.chooseed == true;
        });
        if (ifChooseed.length > 0) {
          let spanIndex = typeof props.spanIndex != 'undefined' ? props.spanIndex : -1;
          ctx.emit('chooseOptions', filterValue.value, ifChooseed[0], spanIndex);
        } else {
          filterValue.value = filterValue.value.split('：')[0] + '：';
          isOptionsShow.value = true;
        }
        // return;
      }

      return {
        divComInputFilter,
        foucus,
        inputWidth,
        divLeft,
        filterValue,
        focusObj,
        isEmptyItem,
        aComInputFilter,
        singleSearchOptions,
        isOptionsShow,
        ifTextarea,
        emptyLength,
        pressEnter,
        onKeyDownDelete,
        onKeyUpDelete,
        chooseOption,
        closeDiv,
        openDiv,
        checkDefault,
        changeDefalutValue,
        showOptionsContent,
      };
    },
  });
</script>
<style lang="less" scoped>
  .ant-input:focus {
    border: transparent !important;
    box-shadow: none !important;
  }
  .show-options-content {
    position: absolute;
    z-index: 9;
    left: v-bind(divLeft);
  }
  .ns-input-filter-list {
    border-radius: 0;
    background-color: #fff;
    box-shadow: 0 0 16px 0 rgb(54 58 80 / 16%);
    min-width: 120px;
    color: rgba(0, 0, 0, 0.9);
  }
  .options-list-text {
    overflow-y: auto;
    padding: 0;
    list-style: none;
    color: rgba(0, 0, 0, 0.9);
    margin: 0px;
    max-height: 180px;
  }
  .is-disabled {
    background-color: transparent;
    color: rgba(0, 0, 0, 0.25);
    cursor: not-allowed;
    font-size: 12px;
    margin-bottom: 0px;
    padding: 6px 10px;
  }
  .options-list-text > li:first-child,
  .options-list-text > li:last-child {
    border-radius: 0 0 0 0;
  }
  .options-list-text > li:hover {
    background-color: #ebeef2;
  }
  .options-list-text > li {
    margin-bottom: 0;
    font-size: 12px;
    padding: 6px 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #000;
    display: block;
    cursor: pointer;
    line-height: 14px;
  }
  .options-list-text > li.choose-li {
    background-color: #00acff;
    color: #fff;
  }
  .input-textarea-span {
    display: inline-block;
    box-sizing: border-box;
    vertical-align: top;
    height: 28px;
    font-size: 12px;
    border: 1px solid rgb(207, 213, 222);
    border-radius: 0px;
    background-color: rgb(255, 255, 255);
    color: rgba(0, 0, 0, 0.9);
    transition: color 0.2s ease-in-out 0s, background-color, border;
    padding: 3px 0px !important;
    min-height: 22px !important;
    line-height: 22px !important;
    resize: none;
  }
</style>
