import { jsx, jsxs } from "react/jsx-runtime";
import { Row } from "../../layouts/index.js";
import { Position } from "../../xyflow/react.js";
import { memo, useCallback, useEffect, useRef } from "react";
import { cx } from "../../utils/CssUtil.js";
import { NodeViewportOverlay } from "../NodeViewportOverlay.js";
import { CanvasInlineButton } from "./CanvasInlineButton.js";
import { LABEL_SHADOW_STYLE } from "./HandleLabel.js";
const BUTTON_POSITION = {
    [Position.Top]: 'flex-col-reverse bottom-full left-1/2 -translate-x-1/2',
    [Position.Bottom]: 'flex-col top-full left-1/2 -translate-x-1/2',
    [Position.Left]: 'flex-row-reverse right-full top-1/2 -translate-y-1/2',
    [Position.Right]: 'flex-row left-full top-1/2 -translate-y-1/2'
};
const DRAG_THRESHOLD = 5;
const HandleButton = /*#__PURE__*/ memo(({ visible, labelVisible, keepButtonMounted = false, position, onAction, onMouseEnter, onMouseLeave, handleRef, label, labelIcon, labelBackgroundColor, portal })=>{
    const didDragRef = useRef(false);
    const teardownRef = useRef(null);
    useEffect(()=>()=>teardownRef.current?.(), []);
    const handleClick = useCallback((e)=>{
        e.stopPropagation();
        if (didDragRef.current) return;
        onAction(e);
    }, [
        onAction
    ]);
    const handlePointerDown = useCallback((e)=>{
        teardownRef.current?.();
        didDragRef.current = false;
        const startX = e.clientX;
        const startY = e.clientY;
        const onMove = (moveEvt)=>{
            if (didDragRef.current) return;
            const dx = moveEvt.clientX - startX;
            const dy = moveEvt.clientY - startY;
            if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) return;
            didDragRef.current = true;
            const handleEl = handleRef?.current;
            if (handleEl) {
                const rect = handleEl.getBoundingClientRect();
                handleEl.dispatchEvent(new MouseEvent('mousedown', {
                    bubbles: true,
                    cancelable: true,
                    clientX: rect.left + rect.width / 2,
                    clientY: rect.top + rect.height / 2
                }));
                handleEl.dispatchEvent(new MouseEvent('mouseout', {
                    bubbles: true,
                    relatedTarget: document.body
                }));
            }
        };
        const cleanup = ()=>{
            document.removeEventListener('pointermove', onMove);
            document.removeEventListener('pointerup', cleanup);
            document.removeEventListener('pointercancel', cleanup);
            teardownRef.current = null;
        };
        document.addEventListener('pointermove', onMove);
        document.addEventListener('pointerup', cleanup);
        document.addEventListener('pointercancel', cleanup);
        teardownRef.current = cleanup;
    }, []);
    const addButton = keepButtonMounted ? /*#__PURE__*/ jsx(CanvasInlineButton, {
        "aria-label": "Add node",
        "aria-hidden": visible ? void 0 : true,
        disabled: visible ? void 0 : true,
        onClick: handleClick,
        onPointerDown: handlePointerDown,
        onMouseEnter: onMouseEnter,
        onMouseLeave: onMouseLeave,
        className: cx('nodrag nopan transition-opacity duration-250', visible ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0 disabled:opacity-0')
    }) : visible && /*#__PURE__*/ jsx(CanvasInlineButton, {
        "aria-label": "Add node",
        onClick: handleClick,
        onPointerDown: handlePointerDown,
        onMouseEnter: onMouseEnter,
        onMouseLeave: onMouseLeave,
        className: "nodrag nopan pointer-events-auto animate-fade-in"
    });
    const content = /*#__PURE__*/ jsxs("div", {
        className: cx('absolute flex items-center pointer-events-none', BUTTON_POSITION[position]),
        children: [
            addButton,
            label && /*#__PURE__*/ jsx(InlineLabel, {
                label: label,
                labelIcon: labelIcon,
                backgroundColor: labelBackgroundColor,
                visible: labelVisible
            })
        ]
    });
    const shouldRenderPortal = Boolean(keepButtonMounted || visible || label && labelVisible);
    if (portal) {
        if (!shouldRenderPortal) return null;
        const { nodeId, ...anchor } = portal;
        return /*#__PURE__*/ jsx(NodeViewportOverlay, {
            nodeId: nodeId,
            anchor: anchor,
            layer: "nodeHandleAffordance",
            children: content
        });
    }
    return content;
});
const InlineLabel = ({ label, labelIcon, backgroundColor, visible = true })=>/*#__PURE__*/ jsx("div", {
        "aria-hidden": visible ? void 0 : true,
        className: cx('px-1.5 py-0.5 rounded-sm whitespace-nowrap select-none transition-opacity duration-250 z-10', visible ? 'opacity-100' : 'opacity-0'),
        style: backgroundColor ? {
            backgroundColor
        } : void 0,
        children: /*#__PURE__*/ jsxs(Row, {
            align: "center",
            gap: 4,
            children: [
                labelIcon,
                /*#__PURE__*/ jsx("span", {
                    className: "text-xs font-bold text-foreground-muted",
                    style: backgroundColor ? void 0 : LABEL_SHADOW_STYLE,
                    children: label
                })
            ]
        })
    });
const BRIDGE_BASE = 'absolute pointer-events-auto cursor-default';
const BRIDGE_POSITION = {
    [Position.Top]: 'bottom-full left-0 w-full',
    [Position.Bottom]: 'top-full left-0 w-full',
    [Position.Left]: 'right-full top-0 h-full',
    [Position.Right]: 'left-full top-0 h-full'
};
const HandleHoverBridge = /*#__PURE__*/ memo(({ position, visible })=>{
    if (!visible) return null;
    const isVertical = position === Position.Top || position === Position.Bottom;
    return /*#__PURE__*/ jsx("div", {
        className: cx(BRIDGE_BASE, BRIDGE_POSITION[position], isVertical ? 'h-15' : 'w-15')
    });
});
export { HandleButton, HandleHoverBridge };
