import { PluginContainerData_Alignment } from "./../../ricos-schema/next-schema/index.js";
import { getElementScale } from "./../../_shared/get-element-scale.js";
import styles from "../statics/styles-scss.js";
const handleClasses = {
  right: [styles.handlerRight, "ricos-resize-handler-right"].join(" "),
  left: styles.handlerLeft,
  top: styles.handlerTop,
  bottom: styles.handlerBottom,
  topLeft: styles.handlerTopLeft,
  topRight: styles.handlerTopRight,
  bottomRight: styles.handlerBottomRight,
  bottomLeft: styles.handlerBottomLeft
};
const OVERDRAG_ENTER_THRESHOLD = 20;
const createResizeHandler = ({
  resizeElement,
  isEnabled,
  getMinWidth,
  getMaxWidth,
  enable,
  lockAspectRatio,
  setMaxWidthAsPercentage = false,
  alignment,
  onResize,
  onResizeStop
}) => {
  if (!isEnabled) {
    return () => {
    };
  }
  const originalWidth = resizeElement.offsetWidth;
  const originalHeight = resizeElement.offsetHeight;
  let aspectRatio = originalWidth / originalHeight;
  resizeElement.setAttribute("data-hook", "ricos-resizer");
  const originalPosition = resizeElement.style.position;
  if (!originalPosition || originalPosition === "static") {
    resizeElement.style.position = "relative";
  }
  const handles = {};
  const handleListeners = {};
  const directions = [
    "left",
    "right",
    "top",
    "bottom",
    "topLeft",
    "topRight",
    "bottomRight",
    "bottomLeft"
  ];
  directions.forEach((direction) => {
    if (enable[direction]) {
      const handle = document.createElement("div");
      handle.className = handleClasses[direction] || "";
      handle.setAttribute("data-hook", `ricos-resize-handler-${direction}`);
      handle.setAttribute("data-resize-handle", direction);
      resizeElement.appendChild(handle);
      handles[direction] = handle;
    }
  });
  let currentDirection = null;
  let currentHandle = null;
  let currentPointerId = null;
  let startX = 0;
  let startY = 0;
  let startWidth = 0;
  let startHeight = 0;
  let scale = { scaleX: 1, scaleY: 1 };
  let lastIsExceedingMaxWidth = false;
  let overdragReferenceMaxWidth = 0;
  const getDirectionMultipliers = (direction) => {
    const multipliers = { x: 0, y: 0 };
    if (direction.includes("Right") || direction === "right") {
      multipliers.x = 1;
    } else if (direction.includes("Left") || direction === "left") {
      multipliers.x = -1;
    }
    if (direction.includes("Bottom") || direction === "bottom") {
      multipliers.y = 1;
    } else if (direction.includes("Top") || direction === "top") {
      multipliers.y = -1;
    }
    return multipliers;
  };
  const calculateNewDimensions = (deltaX, deltaY, direction) => {
    const multipliers = getDirectionMultipliers(direction);
    const scaledDeltaX = deltaX / scale.scaleX;
    const scaledDeltaY = deltaY / scale.scaleY;
    const isCentered = alignment !== PluginContainerData_Alignment.LEFT && alignment !== PluginContainerData_Alignment.RIGHT;
    const isHorizontalSideResize = direction === "left" || direction === "right";
    const isCornerResize = ["topLeft", "topRight", "bottomLeft", "bottomRight"].includes(direction);
    const adjustedDeltaX = isCentered && (isHorizontalSideResize || isCornerResize) ? scaledDeltaX * 2 : scaledDeltaX;
    let newWidth = startWidth + adjustedDeltaX * multipliers.x;
    let newHeight = startHeight + scaledDeltaY * multipliers.y;
    const minWidth = getMinWidth();
    const maxWidth = getMaxWidth();
    const unclampedNewWidth = newWidth;
    newWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));
    if (lockAspectRatio) {
      if (isCornerResize) {
        const widthFromX = startWidth + adjustedDeltaX * multipliers.x;
        const widthFromY = (startHeight + scaledDeltaY * multipliers.y) * aspectRatio;
        const isExpanding = adjustedDeltaX * multipliers.x > 0 || scaledDeltaY * multipliers.y > 0;
        if (isExpanding) {
          newWidth = Math.max(widthFromX, widthFromY);
        } else {
          newWidth = Math.min(widthFromX, widthFromY);
        }
        newWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));
        newHeight = newWidth / aspectRatio;
      } else if (multipliers.x !== 0) {
        newHeight = newWidth / aspectRatio;
      } else if (multipliers.y !== 0) {
        newWidth = newHeight * aspectRatio;
        newWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));
        newHeight = newWidth / aspectRatio;
      }
    }
    const isExceedingMaxWidth = lastIsExceedingMaxWidth ? unclampedNewWidth > overdragReferenceMaxWidth : unclampedNewWidth - overdragReferenceMaxWidth > OVERDRAG_ENTER_THRESHOLD;
    return {
      width: Math.round(newWidth),
      height: Math.round(newHeight),
      isMaxWidth: Math.abs(newWidth - maxWidth) < 1,
      isMinWidth: Math.abs(newWidth - minWidth) < 1,
      isExceedingMaxWidth
    };
  };
  const removePointerListeners = (handleEl) => {
    handleEl.removeEventListener("pointermove", handlePointerMove);
    handleEl.removeEventListener("pointerup", handlePointerUp);
    handleEl.removeEventListener("pointercancel", handlePointerUp);
    handleEl.removeEventListener("lostpointercapture", handleLostPointerCapture);
  };
  const finishResize = () => {
    if (!currentHandle || currentPointerId === null) {
      return;
    }
    if (currentHandle.hasPointerCapture(currentPointerId)) {
      currentHandle.releasePointerCapture(currentPointerId);
    }
    removePointerListeners(currentHandle);
    const width = resizeElement.offsetWidth;
    const height = resizeElement.offsetHeight;
    const minWidth = getMinWidth();
    const maxWidth = getMaxWidth();
    resizeElement.style.removeProperty("width");
    resizeElement.style.removeProperty("maxWidth");
    (resizeElement.closest("[data-resize-container]") ?? resizeElement)?.style.removeProperty("--ricos-internal-resize-width");
    onResizeStop({
      width,
      height,
      isMinWidth: width === minWidth,
      isMaxWidth: width === maxWidth,
      isExceedingMaxWidth: lastIsExceedingMaxWidth
    });
    currentDirection = null;
    currentHandle = null;
    currentPointerId = null;
    lastIsExceedingMaxWidth = false;
  };
  const handleLostPointerCapture = (event) => {
    if (currentPointerId === null || event.pointerId !== currentPointerId) {
      return;
    }
    finishResize();
  };
  const handlePointerDown = (direction, handle) => (event) => {
    if (event.button !== 0) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
    currentDirection = direction;
    currentHandle = handle;
    currentPointerId = event.pointerId;
    startX = event.clientX;
    startY = event.clientY;
    startWidth = resizeElement.offsetWidth;
    startHeight = resizeElement.offsetHeight;
    aspectRatio = startWidth / startHeight;
    scale = getElementScale(resizeElement);
    overdragReferenceMaxWidth = getMaxWidth();
    lastIsExceedingMaxWidth = false;
    handle.setPointerCapture(event.pointerId);
    handle.addEventListener("pointermove", handlePointerMove);
    handle.addEventListener("pointerup", handlePointerUp);
    handle.addEventListener("pointercancel", handlePointerUp);
    handle.addEventListener("lostpointercapture", handleLostPointerCapture);
  };
  const handlePointerMove = (event) => {
    if (!currentDirection || currentPointerId === null || currentPointerId !== event.pointerId) {
      return;
    }
    const deltaX = event.clientX - startX;
    const deltaY = event.clientY - startY;
    const { width, height, isMinWidth, isMaxWidth, isExceedingMaxWidth } = calculateNewDimensions(
      deltaX,
      deltaY,
      currentDirection
    );
    lastIsExceedingMaxWidth = isExceedingMaxWidth;
    let widthToSet = `${width}px`;
    if (setMaxWidthAsPercentage && isMaxWidth || isExceedingMaxWidth) {
      widthToSet = `100%`;
    }
    resizeElement.style.width = widthToSet;
    resizeElement.style.maxWidth = "100%";
    (resizeElement.closest("[data-resize-container]") ?? resizeElement)?.style.setProperty("--ricos-internal-resize-width", widthToSet);
    onResize({ width, height, isMinWidth, isMaxWidth, isExceedingMaxWidth });
  };
  const handlePointerUp = (event) => {
    if (currentHandle === null || currentPointerId === null) {
      return;
    }
    if (currentPointerId !== event.pointerId) {
      finishResize();
      return;
    }
    finishResize();
  };
  Object.entries(handles).forEach(([direction, handle]) => {
    const listener = handlePointerDown(direction, handle);
    handleListeners[direction] = listener;
    handle.addEventListener("pointerdown", listener);
  });
  return () => {
    if (currentHandle && currentPointerId !== null) {
      if (currentHandle.hasPointerCapture(currentPointerId)) {
        currentHandle.releasePointerCapture(currentPointerId);
      }
      removePointerListeners(currentHandle);
    }
    Object.entries(handles).forEach(([direction, handle]) => {
      const listener = handleListeners[direction];
      if (listener) {
        handle.removeEventListener("pointerdown", listener);
      }
    });
    Object.values(handles).forEach((handle) => {
      if (handle.parentNode === resizeElement) {
        resizeElement.removeChild(handle);
      }
    });
    resizeElement.removeAttribute("data-hook");
    if (!originalPosition || originalPosition === "static") {
      resizeElement.style.position = originalPosition || "";
    }
  };
};
export {
  createResizeHandler
};
//# sourceMappingURL=create-resize-handler.js.map
