import { nextTick } from "vue";
import XEUtils from "xe-utils";
import "../../../ui/index.mjs";
import { getAbsolutePos, getEventTargetNode, getDomNode } from "../../../ui/src/dom.mjs";
import { hasChildrenList, isEnableConf } from "../../../ui/src/utils.mjs";
import { VxeUI } from "../../../../../@vxe-ui/core/es/index.esm.mjs";
const { menus, hooks, globalEvents, GLOBAL_EVENT_KEYS } = VxeUI;
const tableMenuMethodKeys = ["closeMenu"];
hooks.add("tableMenuModule", {
  setupTable($xeTable) {
    const { xID, props, reactData, internalData } = $xeTable;
    const { refElem, refTableFilter, refTableMenu } = $xeTable.getRefMaps();
    const { computeMouseOpts, computeIsContentMenu, computeMenuOpts } = $xeTable.getComputeMaps();
    const $xeGrid = $xeTable.xeGrid;
    const $xeGantt = $xeTable.xeGantt;
    const $xeGGWrapper = $xeGrid || $xeGantt;
    let menuMethods = {};
    let menuPrivateMethods = {};
    const handleOpenMenuEvent = (evnt, type, params) => {
      const { ctxMenuStore } = reactData;
      const isContentMenu = computeIsContentMenu.value;
      const menuOpts = computeMenuOpts.value;
      const config = menuOpts[type];
      const { transfer, visibleMethod } = menuOpts;
      if (config) {
        const { options, disabled } = config;
        if (disabled) {
          evnt.preventDefault();
        } else if (isContentMenu && options && options.length) {
          params.options = options;
          $xeTable.preventEvent(evnt, "event.showMenu", params, () => {
            if (!visibleMethod || visibleMethod(params)) {
              evnt.preventDefault();
              $xeTable.updateZindex();
              const el = $xeGGWrapper ? $xeGGWrapper.getRefMaps().refElem.value : refElem.value;
              if (!el) {
                return;
              }
              const tableRect = el.getBoundingClientRect();
              const { scrollTop, scrollLeft, visibleHeight, visibleWidth } = getDomNode();
              let top = evnt.clientY - tableRect.y;
              let left = evnt.clientX - tableRect.x;
              if (transfer) {
                top = evnt.clientY + scrollTop;
                left = evnt.clientX + scrollLeft;
              }
              const handleVisible = () => {
                internalData._currMenuParams = params;
                Object.assign(ctxMenuStore, {
                  visible: true,
                  list: options,
                  selected: null,
                  selectChild: null,
                  showChild: false,
                  style: {
                    zIndex: internalData.tZindex,
                    top: `${top}px`,
                    left: `${left}px`
                  }
                });
                nextTick(() => {
                  const tableMenu = refTableMenu.value;
                  const ctxElem = tableMenu.getRefMaps().refElem.value;
                  const clientHeight = ctxElem.clientHeight;
                  const clientWidth = ctxElem.clientWidth;
                  const { boundingTop, boundingLeft } = getAbsolutePos(ctxElem);
                  const offsetTop = boundingTop + clientHeight - visibleHeight;
                  const offsetLeft = boundingLeft + clientWidth - visibleWidth;
                  if (offsetTop > -10) {
                    ctxMenuStore.style.top = `${Math.max(scrollTop + 2, top - clientHeight - 2)}px`;
                  }
                  if (offsetLeft > -10) {
                    ctxMenuStore.style.left = `${Math.max(scrollLeft + 2, left - clientWidth - 2)}px`;
                  }
                });
              };
              const { keyboard, row, column } = params;
              if (keyboard && row && column) {
                $xeTable.scrollToRow(row, column).then(() => {
                  const cell = $xeTable.getCellElement(row, column);
                  if (cell) {
                    const { boundingTop, boundingLeft } = getAbsolutePos(cell);
                    top = boundingTop + scrollTop + Math.floor(cell.offsetHeight / 2);
                    left = boundingLeft + scrollLeft + Math.floor(cell.offsetWidth / 2);
                  }
                  handleVisible();
                });
              } else {
                handleVisible();
              }
            } else {
              menuMethods.closeMenu();
            }
          });
        }
      }
      $xeTable.closeFilter();
    };
    menuMethods = {
      /**
       * 关闭快捷菜单
       */
      closeMenu() {
        Object.assign(reactData.ctxMenuStore, {
          visible: false,
          selected: null,
          selectChild: null,
          showChild: false
        });
        return nextTick();
      }
    };
    menuPrivateMethods = {
      /**
       * 处理菜单的移动
       */
      moveCtxMenu(evnt, ctxMenuStore, property, hasOper, operRest, menuList) {
        let selectItem;
        const selectIndex = XEUtils.findIndexOf(menuList, (item) => ctxMenuStore[property] === item);
        if (hasOper) {
          if (operRest && hasChildrenList(ctxMenuStore.selected)) {
            ctxMenuStore.showChild = true;
          } else {
            ctxMenuStore.showChild = false;
            ctxMenuStore.selectChild = null;
          }
        } else if (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP)) {
          for (let len = selectIndex - 1; len >= 0; len--) {
            if (menuList[len].visible !== false) {
              selectItem = menuList[len];
              break;
            }
          }
          ctxMenuStore[property] = selectItem || menuList[menuList.length - 1];
        } else if (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN)) {
          for (let index = selectIndex + 1; index < menuList.length; index++) {
            if (menuList[index].visible !== false) {
              selectItem = menuList[index];
              break;
            }
          }
          ctxMenuStore[property] = selectItem || menuList[0];
        } else if (ctxMenuStore[property] && (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER) || globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.SPACEBAR))) {
          $xeTable.ctxMenuLinkEvent(evnt, ctxMenuStore[property]);
        }
      },
      handleOpenMenuEvent,
      /**
       * 快捷菜单事件处理
       */
      handleGlobalContextmenuEvent(evnt) {
        const $xeGrid2 = $xeTable.xeGrid;
        const $xeGantt2 = $xeTable.xeGantt;
        const { mouseConfig, menuConfig } = props;
        const { editStore, ctxMenuStore } = reactData;
        const { visibleColumn } = internalData;
        const tableFilter = refTableFilter.value;
        const tableMenu = refTableMenu.value;
        const mouseOpts = computeMouseOpts.value;
        const menuOpts = computeMenuOpts.value;
        const el = refElem.value;
        const { selected } = editStore;
        const layoutList = ["header", "body", "footer"];
        if (isEnableConf(menuConfig)) {
          if (ctxMenuStore.visible && tableMenu && getEventTargetNode(evnt, tableMenu.getRefMaps().refElem.value).flag) {
            evnt.preventDefault();
            return;
          }
          if (internalData._keyCtx) {
            const type = "body";
            const params = { source: "table", type, $table: $xeTable, $grid: $xeGrid2, $gantt: $xeGantt2, keyboard: true, columns: visibleColumn.slice(0), $event: evnt };
            if (mouseConfig && mouseOpts.area) {
              const activeArea = $xeTable.getActiveCellArea();
              if (activeArea && activeArea.row && activeArea.column) {
                params.row = activeArea.row;
                params.column = activeArea.column;
                handleOpenMenuEvent(evnt, type, params);
                return;
              }
            } else if (mouseConfig && mouseOpts.selected) {
              if (selected.row && selected.column) {
                params.row = selected.row;
                params.column = selected.column;
                handleOpenMenuEvent(evnt, type, params);
                return;
              }
            }
          }
          for (let index = 0; index < layoutList.length; index++) {
            const layout = layoutList[index];
            const columnTargetNode = getEventTargetNode(evnt, el, `vxe-${layout}--column`, (target) => {
              return target.parentNode.parentNode.parentNode.getAttribute("xid") === xID;
            });
            const params = { source: "table", type: layout, $table: $xeTable, $grid: $xeGrid2, $gantt: $xeGantt2, columns: visibleColumn.slice(0), $event: evnt };
            if (columnTargetNode.flag) {
              const cell = columnTargetNode.targetElem;
              const columnNodeRest = $xeTable.getColumnNode(cell);
              const column = columnNodeRest ? columnNodeRest.item : null;
              let typePrefix = `${layout}-`;
              if (column) {
                Object.assign(params, { column, columnIndex: $xeTable.getColumnIndex(column), cell });
              }
              if (layout === "body") {
                const rowNodeRest = $xeTable.getRowNode(cell.parentNode);
                const row = rowNodeRest ? rowNodeRest.item : null;
                typePrefix = "";
                if (row) {
                  params.row = row;
                  params.rowIndex = $xeTable.getRowIndex(row);
                }
              }
              const eventType = `${typePrefix}cell-menu`;
              handleOpenMenuEvent(evnt, layout, params);
              $xeTable.dispatchEvent(eventType, params, evnt);
              return;
            } else if (getEventTargetNode(evnt, el, `vxe-table--${layout}-wrapper`, (target) => target.getAttribute("xid") === xID).flag || layout === "body" && getEventTargetNode(evnt, el, "vxe-table--empty-place-wrapper", (target) => target.getAttribute("xid") === xID).flag) {
              if (menuOpts.trigger === "cell") {
                evnt.preventDefault();
              } else {
                handleOpenMenuEvent(evnt, layout, params);
              }
              return;
            }
          }
        }
        if (tableFilter && !getEventTargetNode(evnt, tableFilter.getRefMaps().refElem.value).flag) {
          $xeTable.closeFilter();
        }
        menuMethods.closeMenu();
      },
      ctxMenuMouseoverEvent(evnt, item, child) {
        const menuElem = evnt.currentTarget;
        const { ctxMenuStore } = reactData;
        evnt.preventDefault();
        evnt.stopPropagation();
        ctxMenuStore.selected = item;
        ctxMenuStore.selectChild = child;
        if (!child) {
          ctxMenuStore.showChild = hasChildrenList(item);
          if (ctxMenuStore.showChild) {
            nextTick(() => {
              const childWrapperElem = menuElem.nextElementSibling;
              if (childWrapperElem) {
                const { boundingTop, boundingLeft, visibleHeight, visibleWidth } = getAbsolutePos(menuElem);
                const posTop = boundingTop + menuElem.offsetHeight;
                const posLeft = boundingLeft + menuElem.offsetWidth;
                let left = "";
                let right = "";
                if (posLeft + childWrapperElem.offsetWidth > visibleWidth - 10) {
                  left = "auto";
                  right = `${menuElem.offsetWidth}px`;
                }
                let top = "";
                let bottom = "";
                if (posTop + childWrapperElem.offsetHeight > visibleHeight - 10) {
                  top = "auto";
                  bottom = "0";
                }
                childWrapperElem.style.left = left;
                childWrapperElem.style.right = right;
                childWrapperElem.style.top = top;
                childWrapperElem.style.bottom = bottom;
              }
            });
          }
        }
      },
      ctxMenuMouseoutEvent(evnt, item) {
        const { ctxMenuStore } = reactData;
        if (!item.children) {
          ctxMenuStore.selected = null;
        }
        ctxMenuStore.selectChild = null;
      },
      /**
       * 快捷菜单点击事件
       */
      ctxMenuLinkEvent(evnt, menu) {
        const $xeGrid2 = $xeTable.xeGrid;
        const $xeGantt2 = $xeTable.xeGantt;
        if (!menu.loading && !menu.disabled && (menu.code || !menu.children || !menu.children.length)) {
          const gMenuOpts = menus.get(menu.code);
          const params = Object.assign({}, internalData._currMenuParams, { menu, $table: $xeTable, $grid: $xeGrid2, $gantt: $xeGantt2, $event: evnt });
          const tmMethod = gMenuOpts ? gMenuOpts.tableMenuMethod || gMenuOpts.menuMethod : null;
          if (tmMethod) {
            tmMethod(params, evnt);
          }
          $xeTable.dispatchEvent("menu-click", params, evnt);
          menuMethods.closeMenu();
        }
      }
    };
    return Object.assign(Object.assign({}, menuMethods), menuPrivateMethods);
  },
  setupGrid($xeGrid) {
    return $xeGrid.extendTableMethods(tableMenuMethodKeys);
  },
  setupGantt($xeGantt) {
    return $xeGantt.extendTableMethods(tableMenuMethodKeys);
  }
});
