import { ref, Ref, watch, defineComponent } from 'vue';
import {
  getDataPickerProps,
  getEditorEmits,
  useNamespace,
} from '@ibiz-template/vue-util';
import '@ibiz-template/theme/style/components/editor/ibiz-picker-dropdown/ibiz-picker-dropdown.scss';
import { isNil } from 'ramda';

export const IBizPickerDropDown = defineComponent({
  name: 'IBizPickerDropDown',
  props: getDataPickerProps(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('picker-dropdown');

    const c = props.controller;

    // 当前文本值
    const curValue: Ref<Array<string> | string | null> = ref('');

    // 实体数据集
    const items: Ref<IData[]> = ref([]);

    // 是否是第一次搜索
    const isFirstSearch = ref(false);

    // 鼠标是否进入
    const isEnter = ref(false);

    // 下拉框是否在展开
    const vsisible = ref(false);

    // 第一次搜索的时候需要保存值，否则回显有问题
    const firstRefValue: Ref<string> = ref('');

    // 是否选择过选项
    const hasSelected = ref(false);

    watch(
      () => props.value,
      (newVal, oldVal) => {
        if (newVal || newVal === null) {
          if (oldVal === undefined || oldVal === null) {
            isFirstSearch.value = true;
          }
          curValue.value = newVal;
          const value = props.data[c.valueItem];
          const index = items.value.findIndex((item: IData) =>
            Object.is(item[c.keyName], value),
          );
          if (index !== -1) {
            return;
          }
          // items里匹配不到当前值项值时，生成自身的选项
          items.value = [];
          if (!isNil(newVal) && !isNil(value)) {
            items.value.push({ [c.textName]: newVal, [c.keyName]: value });
          }
        }
      },
      { immediate: true },
    );

    // 获取关联数据项值
    const refValue = ref('');

    watch(
      () => props.data[c.valueItem],
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          refValue.value = newVal;
          // 如果值项被清空了，主文本也需清空
          if (newVal === null) {
            emit('change', null);
          }
        }
      },
      { immediate: true, deep: true },
    );

    // 加载中
    const loading: Ref<boolean> = ref(false);

    // 往外抛值
    const onACSelect = async (item: IData) => {
      // 处理回填数据
      const dataItems = await c.calcFillDataItems(item);
      if (dataItems.length) {
        dataItems.forEach(dataItem => {
          emit('change', dataItem.value, dataItem.name);
        });
      }

      // 处理值项和本身的值
      if (c.valueItem) {
        emit('change', item[c.keyName], c.valueItem);
      }
      emit('change', item[c.textName]);
    };

    // 值变更
    const onSelect = (select: string | Array<string>) => {
      const index = items.value.findIndex(item =>
        Object.is(item[c.keyName], select),
      );
      if (index >= 0) {
        onACSelect(items.value[index]);
      }
      hasSelected.value = true;
    };

    // 在搜索中时，再次触发搜索记录搜索值，等待上次搜索触发完成后再次搜索
    let waitQuery: string | null = null;

    // 搜索
    const onSearch = async (query: string) => {
      if (c.model.appDataEntity && loading.value === false) {
        loading.value = true;
        // 初次搜索时refValue需要置空，否则选项出不来
        if (isFirstSearch.value) {
          firstRefValue.value = refValue.value;
          refValue.value = '';
        }
        try {
          const searchQuery = isFirstSearch.value ? '' : query;
          const res = await c.getServiceData(searchQuery, props.data!);
          if (res) {
            items.value = res.data as IData[];
          }
        } finally {
          loading.value = false;
          if (waitQuery != null) {
            const selfQuery = waitQuery;
            waitQuery = null;
            await onSearch(selfQuery);
          }
        }
      } else {
        waitQuery = query;
      }
      isFirstSearch.value = false;
    };

    // 下拉打开
    const onOpenChange = (isOpen: boolean) => {
      emit('operate', isOpen);
      if (isOpen) {
        items.value = [];
        onSearch('');
      } else if (!hasSelected.value) {
        // 下拉关闭的时候，如果没有选择过，要把回显值重新赋回select
        refValue.value = firstRefValue.value;
      }
      vsisible.value = isOpen;
    };

    // 搜索词改变时触发
    const onQueryChange = (query: string) => {
      if (query === '') {
        onSearch('');
      }
    };

    // 清除
    const onClear = () => {
      // 清空回填数据
      const dataItems = c.model.deACMode?.dataItems;
      if (dataItems?.length) {
        dataItems.forEach(dataItem => {
          emit('change', null, dataItem.name);
        });
      }
      if (c.valueItem) {
        emit('change', null, c.valueItem);
      }
      emit('change', null);
    };

    const renderIcon = () => {
      if (props.value && isEnter.value) {
        return (
          <i
            class='ivu-icon ivu-icon-ios-close-circle ivu-select-arrow'
            onClick={onClear}
          ></i>
        );
      }
      return <i class='ivu-icon ivu-icon-ios-arrow-down ivu-select-arrow'></i>;
    };

    const onMouseEnter = () => {
      isEnter.value = true;
    };

    const onMouseLevel = () => {
      isEnter.value = false;
    };

    return {
      ns,
      c,
      refValue,
      loading,
      items,
      onOpenChange,
      onQueryChange,
      onClear,
      onSelect,
      onSearch,
      renderIcon,
      onMouseEnter,
      onMouseLevel,
    };
  },
  render(h) {
    if (this.readonly) {
      return (
        <div class={(this.ns.b(), this.ns.m('readonly'))}>{this.value}</div>
      );
    }
    return (
      <div
        class={[this.ns.b(), this.disabled ? this.ns.m('disabled') : '']}
        onMouseenter={this.onMouseEnter}
        onMouseleave={this.onMouseLevel}
      >
        {[
          this.readonly && this.value,
          !this.readonly &&
            h(
              'iSelect',
              {
                props: {
                  ...this.c.customProps,
                  value: this.refValue,
                  filterable: true,
                  remote: true,
                  allowClear: true,
                  clearable: true,
                  transfer: true,
                  loading: this.loading,
                  placeholder: this.c.placeHolder,
                  remoteMethod: this.onSearch,
                  disabled: this.disabled,
                },
                on: {
                  'on-change': this.onSelect,
                  'on-open-change': this.onOpenChange,
                  'on-query-change': this.onQueryChange,
                  'on-clear': this.onClear,
                },
              },
              [
                this.items.map((item, index) => {
                  return (
                    <i-option value={item[this.c.keyName]} key={index}>
                      {item[this.c.textName]}
                    </i-option>
                  );
                }),
              ],
            ),
          this.renderIcon(),
        ]}
      </div>
    );
  },
});
