"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.usePopupControl = usePopupControl;
var _vue = require("vue");
var _utils = require("@grozav/utils");
var _dom = require("@floating-ui/dom");
var _utils2 = require("@inkline/inkline/utils");
function usePopupControl(props) {
  const visible = (0, _vue.ref)(props.componentProps.value.visible);
  const instance = (0, _vue.ref)();
  const animating = (0, _vue.ref)(false);
  const triggerStack = (0, _vue.ref)(0);
  (0, _vue.onMounted)(() => {
    addEventListeners();
  });
  (0, _vue.onUnmounted)(() => {
    removeEventListeners();
  });
  (0, _vue.watch)(() => props.componentProps.value.visible, value => {
    if (value) {
      show();
    } else {
      hide();
    }
  });
  function addEventListeners() {
    const triggerRef = (0, _utils2.extractRefHTMLElement)(props.triggerRef);
    const popupRef = (0, _utils2.extractRefHTMLElement)(props.popupRef);
    if (!triggerRef || !popupRef) {
      return;
    }
    [].concat(props.componentProps.value.events).forEach(trigger => {
      switch (trigger) {
        case "hover":
          (0, _utils.on)(triggerRef, "mouseenter", props.componentProps.value.interactable ? hoverShow : show);
          (0, _utils.on)(triggerRef, "mouseleave", props.componentProps.value.interactable ? hoverHide : hide);
          if (props.componentProps.value.interactable) {
            (0, _utils.on)(popupRef, "mouseenter", hoverShow);
            (0, _utils.on)(popupRef, "mouseleave", hoverHide);
          }
          break;
        case "click":
          (0, _utils.on)(triggerRef, "click", onClick);
          break;
        case "focus":
          for (const child of triggerRef.children) {
            (0, _utils.on)(child, "focus", show);
            (0, _utils.on)(child, "blur", hide);
          }
          break;
        default:
          break;
      }
    });
  }
  function removeEventListeners() {
    const triggerRef = (0, _utils2.extractRefHTMLElement)(props.triggerRef);
    const popupRef = (0, _utils2.extractRefHTMLElement)(props.popupRef);
    if (!triggerRef || !popupRef) {
      return;
    }
    [].concat(props.componentProps.value.events).forEach(trigger => {
      switch (trigger) {
        case "hover":
          (0, _utils.off)(triggerRef, "mouseenter", props.componentProps.value.interactable ? hoverShow : show);
          (0, _utils.off)(triggerRef, "mouseleave", props.componentProps.value.interactable ? hoverHide : hide);
          if (props.componentProps.value.interactable) {
            (0, _utils.off)(popupRef, "mouseenter", hoverShow);
            (0, _utils.off)(popupRef, "mouseleave", hoverHide);
          }
          break;
        case "click":
          (0, _utils.off)(triggerRef, "click", onClick);
          break;
        case "focus":
          for (const child of triggerRef.children) {
            (0, _utils.off)(child, "focus", show);
            (0, _utils.off)(child, "blur", hide);
          }
          break;
        default:
          break;
      }
    });
  }
  function show() {
    if (props.componentProps.value.disabled || props.componentProps.value.readonly || visible.value) {
      return;
    }
    triggerStack.value += 1;
    visible.value = true;
    createPopup();
    props.emit("update:visible", true);
  }
  function hide() {
    if (props.componentProps.value.disabled || props.componentProps.value.readonly || !visible.value) {
      return;
    }
    triggerStack.value -= 1;
    if (triggerStack.value <= 0) {
      triggerStack.value = 0;
      visible.value = false;
      props.emit("update:visible", false);
      setTimeout(() => destroyPopup(), props.componentProps.value.animationDuration);
    }
  }
  function onClick() {
    if (visible.value) {
      hide();
    } else {
      show();
    }
  }
  function onClickOutside() {
    props.emit("click:outside");
    if (!props.componentProps.value.visible) {
      hide();
    }
  }
  function onKeyEscape() {
    hide();
  }
  function hoverShow() {
    animating.value = false;
    show();
  }
  function hoverHide() {
    animating.value = true;
    setTimeout(() => {
      if (animating.value) {
        hide();
      }
    }, props.componentProps.value.hoverHideDelay);
  }
  function createPopup() {
    if (typeof window === "undefined") {
      return;
    }
    const triggerRef = (0, _utils2.extractRefHTMLElement)(props.triggerRef);
    const popupRef = (0, _utils2.extractRefHTMLElement)(props.popupRef);
    const arrowRef = (0, _utils2.extractRefHTMLElement)(props.arrowRef);
    if (!triggerRef || !popupRef) {
      throw new Error("Trigger and popup elements are required.");
    }
    instance.value = (0, _dom.autoUpdate)(triggerRef, popupRef, () => {
      (0, _dom.computePosition)(triggerRef, popupRef, {
        strategy: "absolute",
        placement: props.componentProps.value.placement,
        middleware: [(0, _dom.offset)(props.componentProps.value.offset), (0, _dom.flip)(), (0, _dom.shift)({
          padding: 6
        })].concat(arrowRef ? [(0, _dom.arrow)({
          element: arrowRef
        })] : []),
        ...props.componentProps.value.popupOptions
      }).then(({
        x,
        y,
        placement,
        middlewareData
      }) => {
        Object.assign(popupRef.style, {
          left: `${x}px`,
          top: `${y}px`
        });
        popupRef?.setAttribute("data-popup-placement", placement);
        if (arrowRef) {
          const {
            x: arrowX,
            y: arrowY
          } = middlewareData.arrow;
          const staticSide = {
            top: "bottom",
            right: "left",
            bottom: "top",
            left: "right"
          }[placement.split("-")[0]];
          Object.assign(arrowRef.style, {
            left: arrowX !== null ? `${arrowX}px` : "",
            top: arrowY !== null ? `${arrowY}px` : "",
            right: "",
            bottom: "",
            [staticSide]: "-6px"
          });
        }
      });
    });
  }
  function destroyPopup() {
    if (instance.value) {
      instance.value();
      instance.value = void 0;
    }
  }
  function focusTrigger() {
    const triggerRef = (0, _utils2.extractRefHTMLElement)(props.triggerRef);
    if (!triggerRef) {
      return;
    }
    for (const child of triggerRef.children) {
      if ((0, _utils.focusFirstDescendant)(child)) {
        child.focus();
        break;
      }
    }
  }
  return {
    visible,
    show,
    hide,
    onClick,
    onClickOutside,
    onKeyEscape,
    focusTrigger,
    createPopup,
    destroyPopup
  };
}