import { inject, reactive, ref, computed, watch, onMounted, onUnmounted, provide, h, Teleport, nextTick } from "vue";
import { defineVxeComponent } from "../../ui/src/comp.mjs";
import XEUtils from "xe-utils";
import "../../ui/index.mjs";
import { getEventTargetNode, updatePanelPlacement } from "../../ui/src/dom.mjs";
import { getFuncText, getLastZIndex, nextZIndex } from "../../ui/src/utils.mjs";
import { getSlotVNs } from "../../ui/src/vn.mjs";
import { getConfig } from "../../../../@vxe-ui/core/es/src/config.mjs";
import { useSize } from "../../../../@vxe-ui/core/es/src/useFns.mjs";
import { getI18n } from "../../../../@vxe-ui/core/es/src/i18n.mjs";
import { globalEvents, GLOBAL_EVENT_KEYS, createEvent } from "../../../../@vxe-ui/core/es/src/event.mjs";
import { getIcon } from "../../../../@vxe-ui/core/es/src/icon.mjs";
import { renderEmptyElement } from "../../../../@vxe-ui/core/es/index.esm.mjs";
import { renderer } from "../../../../@vxe-ui/core/es/src/renderer.mjs";
const VxeIconPickerComponent = defineVxeComponent({
  name: "VxeIconPicker",
  props: {
    modelValue: String,
    placeholder: String,
    clearable: Boolean,
    size: {
      type: String,
      default: () => getConfig().iconPicker.size || getConfig().size
    },
    className: [String, Function],
    /**
     * 已废弃，请使用 popupConfig.className
     * @deprecated
     */
    popupClassName: [String, Function],
    showIconTitle: {
      type: Boolean,
      default: () => getConfig().iconPicker.showIconTitle
    },
    readonly: {
      type: Boolean,
      default: null
    },
    disabled: {
      type: Boolean,
      default: null
    },
    icons: Array,
    placement: String,
    popupConfig: Object,
    transfer: {
      type: Boolean,
      default: null
    }
  },
  emits: [
    "update:modelValue",
    "change",
    "clear",
    "click"
  ],
  setup(props, context) {
    const { emit } = context;
    const $xeModal = inject("$xeModal", null);
    const $xeDrawer = inject("$xeDrawer", null);
    const $xeTable = inject("$xeTable", null);
    const $xeForm = inject("$xeForm", null);
    const formItemInfo = inject("xeFormItemInfo", null);
    const xID = XEUtils.uniqueId();
    const { computeSize } = useSize(props);
    const reactData = reactive({
      initialized: false,
      selectIcon: `${props.modelValue || ""}`,
      panelIndex: 0,
      panelStyle: {},
      panelPlacement: null,
      visiblePanel: false,
      isAniVisible: false,
      isActivated: false
    });
    const internalData = {
      // hpTimeout: undefined
    };
    const refElem = ref();
    const refInput = ref();
    const refOptionPanel = ref();
    const refMaps = {
      refElem
    };
    const $xeIconPicker = {
      xID,
      props,
      context,
      reactData,
      getRefMaps: () => refMaps
    };
    let iconPickerMethods = {};
    const computeFormReadonly = computed(() => {
      const { readonly } = props;
      if (readonly === null) {
        if ($xeForm) {
          return $xeForm.props.readonly;
        }
        return false;
      }
      return readonly;
    });
    const computeIsDisabled = computed(() => {
      const { disabled } = props;
      if (disabled === null) {
        if ($xeForm) {
          return $xeForm.props.disabled;
        }
        return false;
      }
      return disabled;
    });
    const computeBtnTransfer = computed(() => {
      const { transfer } = props;
      const popupOpts = computePopupOpts.value;
      if (XEUtils.isBoolean(popupOpts.transfer)) {
        return popupOpts.transfer;
      }
      if (transfer === null) {
        const globalTransfer = getConfig().iconPicker.transfer;
        if (XEUtils.isBoolean(globalTransfer)) {
          return globalTransfer;
        }
        if ($xeTable || $xeModal || $xeDrawer || $xeForm) {
          return true;
        }
      }
      return transfer;
    });
    const computeInpPlaceholder = computed(() => {
      const { placeholder } = props;
      if (placeholder) {
        return getFuncText(placeholder);
      }
      const globalPlaceholder = getConfig().select.placeholder;
      if (globalPlaceholder) {
        return getFuncText(globalPlaceholder);
      }
      return getI18n("vxe.base.pleaseSelect");
    });
    const computeIconList = computed(() => {
      let { icons } = props;
      if (!icons || !icons.length) {
        icons = getConfig().iconPicker.icons || [];
      }
      return icons.map((item) => {
        if (XEUtils.isString(item)) {
          return {
            title: item,
            icon: `vxe-icon-${`${item || ""}`.replace(/^vxe-icon-/, "")}`
          };
        }
        return {
          title: `${item.title || ""}`,
          icon: item.icon || "",
          iconRender: item.iconRender
        };
      });
    });
    const computePopupOpts = computed(() => {
      return Object.assign({}, getConfig().iconPicker.popupConfig, props.popupConfig);
    });
    const computeIconGroupList = computed(() => {
      const iconList = computeIconList.value;
      return XEUtils.chunk(iconList, 4);
    });
    const computeSelectIconItem = computed(() => {
      const { selectIcon } = reactData;
      const iconList = computeIconList.value;
      return selectIcon ? iconList.find((item) => item.icon === selectIcon) : null;
    });
    const updateZindex = () => {
      if (reactData.panelIndex < getLastZIndex()) {
        reactData.panelIndex = nextZIndex();
      }
    };
    const updatePlacement = () => {
      const { placement } = props;
      const { panelIndex } = reactData;
      const targetElem = refElem.value;
      const panelElem = refOptionPanel.value;
      const btnTransfer = computeBtnTransfer.value;
      const popupOpts = computePopupOpts.value;
      const handleStyle = () => {
        const ppObj = updatePanelPlacement(targetElem, panelElem, {
          placement: popupOpts.placement || placement,
          teleportTo: btnTransfer
        });
        const panelStyle = Object.assign(ppObj.style, {
          zIndex: panelIndex
        });
        reactData.panelStyle = panelStyle;
        reactData.panelPlacement = ppObj.placement;
      };
      handleStyle();
      return nextTick().then(handleStyle);
    };
    const showOptionPanel = () => {
      const { hpTimeout } = internalData;
      const isDisabled = computeIsDisabled.value;
      if (!isDisabled) {
        if (hpTimeout) {
          clearTimeout(hpTimeout);
          internalData.hpTimeout = void 0;
        }
        if (!reactData.initialized) {
          reactData.initialized = true;
        }
        reactData.isActivated = true;
        reactData.isAniVisible = true;
        setTimeout(() => {
          reactData.visiblePanel = true;
          updatePlacement();
        }, 10);
        updateZindex();
        updatePlacement();
      }
    };
    const hideOptionPanel = () => {
      reactData.visiblePanel = false;
      internalData.hpTimeout = setTimeout(() => {
        reactData.isAniVisible = false;
      }, 350);
    };
    const changeEvent = (evnt, selectValue) => {
      reactData.selectIcon = selectValue;
      if (selectValue !== props.modelValue) {
        emit("update:modelValue", selectValue);
        dispatchEvent("change", { value: selectValue }, evnt);
        if ($xeForm && formItemInfo) {
          $xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, selectValue);
        }
      }
    };
    const focusEvent = () => {
      const isDisabled = computeIsDisabled.value;
      if (!isDisabled) {
        if (!reactData.visiblePanel) {
          showOptionPanel();
        }
      }
    };
    const blurEvent = () => {
      reactData.isActivated = false;
    };
    const clearValueEvent = (evnt, selectValue) => {
      changeEvent(evnt, selectValue);
      dispatchEvent("clear", { value: selectValue }, evnt);
    };
    const clearEvent = (params, evnt) => {
      clearValueEvent(evnt, null);
      hideOptionPanel();
    };
    const togglePanelEvent = (evnt) => {
      evnt.preventDefault();
      if (reactData.visiblePanel) {
        hideOptionPanel();
      } else {
        showOptionPanel();
      }
    };
    const clickEvent = (evnt) => {
      togglePanelEvent(evnt);
      dispatchEvent("click", {}, evnt);
    };
    const handleGlobalMousewheelEvent = (evnt) => {
      const { visiblePanel } = reactData;
      const isDisabled = computeIsDisabled.value;
      if (!isDisabled) {
        if (visiblePanel) {
          const panelElem = refOptionPanel.value;
          if (getEventTargetNode(evnt, panelElem).flag) {
            updatePlacement();
          } else {
            hideOptionPanel();
          }
        }
      }
    };
    const handleGlobalMousedownEvent = (evnt) => {
      const { visiblePanel } = reactData;
      const isDisabled = computeIsDisabled.value;
      if (!isDisabled) {
        const el = refElem.value;
        const panelElem = refOptionPanel.value;
        reactData.isActivated = getEventTargetNode(evnt, el).flag || getEventTargetNode(evnt, panelElem).flag;
        if (visiblePanel && !reactData.isActivated) {
          hideOptionPanel();
        }
      }
    };
    const handleGlobalKeydownEvent = (evnt) => {
      const { clearable } = props;
      const { visiblePanel } = reactData;
      const isDisabled = computeIsDisabled.value;
      if (!isDisabled) {
        const isTab = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.TAB);
        const isEnter = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER);
        const isEsc = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ESCAPE);
        const isUpArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP);
        const isDwArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN);
        const isDel = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE);
        const isSpacebar = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.SPACEBAR);
        if (isTab) {
          reactData.isActivated = false;
        }
        if (visiblePanel) {
          if (isEsc || isTab) {
            hideOptionPanel();
          } else if (isEnter) {
            evnt.preventDefault();
            evnt.stopPropagation();
          } else if (isUpArrow || isDwArrow) {
            evnt.preventDefault();
          } else if (isSpacebar) {
            evnt.preventDefault();
          }
        } else if ((isUpArrow || isDwArrow || isEnter || isSpacebar) && reactData.isActivated) {
          evnt.preventDefault();
          showOptionPanel();
        }
        if (reactData.isActivated) {
          if (isDel && clearable) {
            clearValueEvent(evnt, null);
          }
        }
      }
    };
    const handleGlobalBlurEvent = () => {
      const { visiblePanel, isActivated } = reactData;
      if (visiblePanel) {
        hideOptionPanel();
      }
      if (isActivated) {
        reactData.isActivated = false;
      }
      if (visiblePanel || isActivated) {
        const $input = refInput.value;
        if ($input) {
          $input.blur();
        }
      }
    };
    const dispatchEvent = (type, params, evnt) => {
      emit(type, createEvent(evnt, { $iconPicker: $xeIconPicker }, params));
    };
    iconPickerMethods = {
      dispatchEvent,
      isPanelVisible() {
        return reactData.visiblePanel;
      },
      togglePanel() {
        if (reactData.visiblePanel) {
          hideOptionPanel();
        } else {
          showOptionPanel();
        }
        return nextTick();
      },
      hidePanel() {
        if (reactData.visiblePanel) {
          hideOptionPanel();
        }
        return nextTick();
      },
      showPanel() {
        if (!reactData.visiblePanel) {
          showOptionPanel();
        }
        return nextTick();
      },
      focus() {
        const $input = refInput.value;
        reactData.isActivated = true;
        if ($input) {
          $input.blur();
        }
        return nextTick();
      },
      blur() {
        const $input = refInput.value;
        if ($input) {
          $input.blur();
        }
        reactData.isActivated = false;
        return nextTick();
      }
    };
    const handleClickIconEvent = (evnt, item) => {
      const value = item.icon;
      changeEvent(evnt, value);
      hideOptionPanel();
    };
    Object.assign($xeIconPicker, iconPickerMethods);
    const renderIconWrapper = () => {
      const { showIconTitle } = props;
      const iconGroupList = computeIconGroupList.value;
      const isDisabled = computeIsDisabled.value;
      return h("div", {
        class: "vxe-ico-picker--list-wrapper"
      }, iconGroupList.map((list) => {
        return h("div", {
          class: "vxe-ico-picker--list"
        }, list.map((item) => {
          const { iconRender } = item;
          const compConf = iconRender ? renderer.get(iconRender.name) : null;
          const oIconMethod = compConf ? compConf.renderIconPickerOptionIcon : null;
          return h("div", {
            class: "vxe-ico-picker--item",
            onClick(evnt) {
              if (!isDisabled) {
                handleClickIconEvent(evnt, item);
              }
            }
          }, [
            h("div", {
              class: "vxe-ico-picker--item-icon"
            }, oIconMethod && iconRender ? getSlotVNs(oIconMethod(iconRender, { $iconPicker: $xeIconPicker, option: item })) : [
              h("i", {
                class: item.icon || ""
              })
            ]),
            showIconTitle ? h("div", {
              class: "vxe-ico-picker--item-title"
            }, `${item.title || ""}`) : renderEmptyElement()
          ]);
        }));
      }));
    };
    const renderIconView = () => {
      const { selectIcon } = reactData;
      const selectIconItem = computeSelectIconItem.value;
      if (selectIconItem) {
        const { iconRender } = selectIconItem;
        const compConf = iconRender ? renderer.get(iconRender.name) : null;
        const oIconMethod = compConf ? compConf.renderIconPickerOptionIcon : null;
        if (oIconMethod && iconRender) {
          return h("div", {
            key: "inc",
            class: "vxe-ico-picker--icon"
          }, getSlotVNs(oIconMethod(iconRender, { $iconPicker: $xeIconPicker, option: selectIconItem })));
        }
      }
      return h("div", {
        key: "ind",
        class: "vxe-ico-picker--icon"
      }, [
        h("i", {
          class: selectIcon
        })
      ]);
    };
    const renderVN = () => {
      const { className, clearable } = props;
      const { initialized, isActivated, isAniVisible, visiblePanel, selectIcon } = reactData;
      const vSize = computeSize.value;
      const isDisabled = computeIsDisabled.value;
      const btnTransfer = computeBtnTransfer.value;
      const formReadonly = computeFormReadonly.value;
      const inpPlaceholder = computeInpPlaceholder.value;
      const popupOpts = computePopupOpts.value;
      const ppClassName = popupOpts.className || props.popupClassName;
      if (formReadonly) {
        return h("div", {
          ref: refElem,
          class: ["vxe-ico-picker--readonly", className]
        }, [
          h("i", {
            class: selectIcon
          })
        ]);
      }
      return h("div", {
        ref: refElem,
        class: ["vxe-ico-picker", className ? XEUtils.isFunction(className) ? className({ $iconPicker: $xeIconPicker }) : className : "", {
          [`size--${vSize}`]: vSize,
          "show--clear": clearable && !isDisabled && !!selectIcon,
          "is--visible": visiblePanel,
          "is--disabled": isDisabled,
          "is--active": isActivated
        }]
      }, [
        h("div", {
          class: "vxe-ico-picker--inner",
          onClick: clickEvent
        }, [
          h("input", {
            ref: refInput,
            class: "vxe-ico-picker--input",
            onFocus: focusEvent,
            onBlur: blurEvent
          }),
          selectIcon ? renderIconView() : h("div", {
            class: "vxe-ico-picker--placeholder"
          }, inpPlaceholder),
          h("div", {
            class: "vxe-ico-picker--suffix"
          }, [
            h("div", {
              class: "vxe-ico-picker--clear-icon",
              onClick: clearEvent
            }, [
              h("i", {
                class: getIcon().INPUT_CLEAR
              })
            ]),
            h("div", {
              class: "vxe-ico-picker--suffix-icon"
            }, [
              h("i", {
                class: visiblePanel ? getIcon().ICON_PICKER_OPEN : getIcon().ICON_PICKER_CLOSE
              })
            ])
          ])
        ]),
        h(Teleport, {
          to: "body",
          disabled: btnTransfer ? !initialized : true
        }, [
          h("div", {
            ref: refOptionPanel,
            class: ["vxe-table--ignore-clear vxe-ico-picker--panel", ppClassName ? XEUtils.isFunction(ppClassName) ? ppClassName({ $iconPicker: $xeIconPicker }) : ppClassName : "", {
              [`size--${vSize}`]: vSize,
              "is--transfer": btnTransfer,
              "ani--leave": isAniVisible,
              "ani--enter": visiblePanel
            }],
            placement: reactData.panelPlacement,
            style: reactData.panelStyle
          }, [
            initialized && (visiblePanel || isAniVisible) ? h("div", {
              class: "vxe-ico-picker--panel-wrapper"
            }, [
              renderIconWrapper()
            ]) : renderEmptyElement()
          ])
        ])
      ]);
    };
    watch(() => props.modelValue, (val) => {
      reactData.selectIcon = `${val || ""}`;
    });
    onMounted(() => {
      globalEvents.on($xeIconPicker, "mousewheel", handleGlobalMousewheelEvent);
      globalEvents.on($xeIconPicker, "mousedown", handleGlobalMousedownEvent);
      globalEvents.on($xeIconPicker, "keydown", handleGlobalKeydownEvent);
      globalEvents.on($xeIconPicker, "blur", handleGlobalBlurEvent);
    });
    onUnmounted(() => {
      globalEvents.off($xeIconPicker, "mousewheel");
      globalEvents.off($xeIconPicker, "mousedown");
      globalEvents.off($xeIconPicker, "keydown");
      globalEvents.off($xeIconPicker, "blur");
    });
    provide("$xeIconPicker", $xeIconPicker);
    $xeIconPicker.renderVN = renderVN;
    return $xeIconPicker;
  },
  render() {
    return this.renderVN();
  }
});
export {
  VxeIconPickerComponent as default
};
