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

export const IBizDropdown = defineComponent({
  name: 'IBizDropdown',
  props: getDropdownProps(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('dropdown');
    const c = props.controller;

    // 是否是树形
    const hasChildren = ref(false);

    // 代码表
    const items: Ref<readonly IData[]> = ref([]);

    c!.loadCodeList(props.data!).then((codeList: readonly IData[]) => {
      items.value = codeList;
      for (let i = 0; i < codeList.length; i++) {
        const _item = codeList[i];
        if (_item.children) {
          hasChildren.value = true;
          break;
        }
      }
    });

    // 当前值
    const curValue: Ref<Array<string> | string | undefined> = computed({
      get() {
        if (props.value) {
          return c!.multiple ? props.value?.split(',') : props.value;
        }
        return props.value;
      },
      set(select: string | Array<string> | undefined) {
        if (Array.isArray(select)) {
          emit('change', select.length === 0 ? null : select.join(','));
        } else {
          emit('change', select);
        }
      },
    });

    const valueText = computed(() => {
      const valueArr = Array.isArray(curValue.value)
        ? curValue.value
        : [curValue.value];

      return items.value
        .filter(item => valueArr.includes(item.value))
        .map(item => item.text)
        .join(',');
    });

    const inputRef = ref();

    if (props.autoFocus) {
      watch(inputRef, newVal => {
        if (newVal) {
          newVal.toggleMenu();
        }
      });
    }

    const onSelect = (value: string | Array<string> | undefined) => {
      curValue.value = value;
    };

    const onOpenChange = (isOpen: boolean) => {
      emit('operate', isOpen);
    };

    // 自定义项显示标签
    const customItemText = (item: IData) => {
      if (item && Object.keys(item).length > 0) {
        return c.customLabel.replace(/\$\{([^}]+)\}/g, (match, key) =>
          Object.hasOwnProperty.call(item, key) ? item[key] : '',
        );
      }
      return '';
    };

    return {
      ns,
      c,
      curValue,
      items,
      valueText,
      hasChildren,
      onOpenChange,
      inputRef,
      onSelect,
      customItemText,
    };
  },

  render(h) {
    return (
      <div
        class={[
          this.ns.b(),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
        ]}
      >
        {[
          this.readonly && this.valueText,
          !this.readonly && this.hasChildren && (
            <app-select-tree
              class={[this.ns.e('tree-select')]}
              value={this.curValue}
              nodes-data={this.items}
              disabled={this.disabled}
              multiple={this.c!.multiple}
            ></app-select-tree>
          ),
          !this.readonly &&
            !this.hasChildren &&
            h(
              'iSelect',
              {
                ref: 'inputRef',
                class: this.ns.e('select'),
                props: {
                  ...this.c.customProps,
                  value: this.curValue,
                  allowClear: true,
                  transfer: true,
                  filterable: true,
                  clearable: true,
                  multiple: this.c!.multiple,
                  placeholder: this.c.placeHolder,
                  disabled: this.disabled,
                },
                on: {
                  'on-change': this.onSelect,
                  'on-open-change': this.onOpenChange,
                },
              },
              [
                this.items.map(item => {
                  return (
                    <i-option
                      value={item.value}
                      tag={item.text}
                      label={item.text}
                    >
                      {this.c.customLabel
                        ? this.customItemText(item.data)
                        : item.text}
                    </i-option>
                  );
                }),
              ],
            ),
        ]}
      </div>
    );
  },
});
