import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useRef, useState } from "react";
import { useEditContext } from "../client/editContext";
import { PictureEditor } from "../PictureEditor";
import { ImageEditor } from "../ImageEditor";
import { getComponentById } from "../componentTreeHelper";
import { showComponentContextMenu } from "../ContextMenu";
import { loadFieldButtons } from "../services/editService";
import { measureBridgeFieldRect, rectEquals, } from "./overlay/geometry";
import { useOverlayMeasurement } from "./overlay/useOverlayMeasurement";
export function PictureEditorOverlay({ pageViewContext, }) {
    const editContext = useEditContext();
    const iframe = pageViewContext?.editorIframe;
    const [field, setField] = useState();
    const [variantName, setVariantName] = useState();
    const [bridgeTarget, setBridgeTarget] = useState();
    const activeBridgeTargetRef = useRef(undefined);
    const editContextRef = useRef(editContext);
    // Track if a dialog is open (e.g., crop dialog) to prevent overlay from hiding
    const [isDialogOpen, setIsDialogOpen] = useState(false);
    const isDialogOpenRef = useRef(false);
    useEffect(() => {
        isDialogOpenRef.current = isDialogOpen;
    }, [isDialogOpen]);
    useEffect(() => {
        editContextRef.current = editContext;
    }, [editContext]);
    useEffect(() => {
        activeBridgeTargetRef.current = bridgeTarget;
    }, [bridgeTarget]);
    useEffect(() => {
        if (isDialogOpenRef.current)
            return;
        const interaction = pageViewContext?.bridgeInteraction;
        if (!interaction || interaction.kind !== "hover")
            return;
        const target = getBridgePictureTarget(interaction, pageViewContext?.pageItemDescriptor ||
            editContextRef.current?.currentItemDescriptor);
        if (!target) {
            setBridgeTarget(undefined);
            setField(undefined);
            setVariantName(undefined);
            return;
        }
        setBridgeTarget((previous) => bridgePictureTargetsEqual(previous, target) ? previous : target);
    }, [pageViewContext?.bridgeInteraction, pageViewContext?.pageItemDescriptor]);
    const bounds = useOverlayMeasurement((metrics) => {
        if (!bridgeTarget || !pageViewContext)
            return null;
        return measureBridgeFieldRect(pageViewContext.bridgeGeometry, pageViewContext.bridgeStructure, {
            fieldId: bridgeTarget.fieldId,
            item: bridgeTarget.item,
        }, metrics);
    }, [
        bridgeTarget,
        pageViewContext?.bridgeGeometry,
        pageViewContext?.bridgeStructure,
    ], {
        initialValue: null,
        equals: rectEquals,
        interests: ["viewport", "layout", "text", "adornment-data"],
    });
    useEffect(() => {
        const loadField = async () => {
            if (bridgeTarget) {
                if (pageViewContext?.page &&
                    editContextRef.current?.showLayoutComponents === false &&
                    bridgeTarget.componentId) {
                    const component = getComponentById(bridgeTarget.componentId, pageViewContext.page);
                    if (component?.layoutId) {
                        setField(undefined);
                        setVariantName(undefined);
                        setBridgeTarget(undefined);
                        return;
                    }
                }
                await loadMediaField(bridgeTarget.fieldId, bridgeTarget.item, bridgeTarget.variantName);
            }
            else {
                setField(undefined);
                setVariantName(undefined);
            }
        };
        const loadMediaField = async (fieldId, itemDescriptor, variantHint) => {
            const item = await editContextRef.current?.itemsRepository.getItem(itemDescriptor);
            const mediaField = item?.fields.find((f) => f.id === fieldId);
            if (!mediaField || !isEditableMediaField(mediaField)) {
                setField(undefined);
                setVariantName(undefined);
                return;
            }
            setField(mediaField);
            if (mediaField.type === "picture") {
                const pictureField = mediaField;
                setVariantName(variantHint ||
                    pictureField.value?.variants?.find((variant) => variant.name)?.name);
            }
            else {
                setVariantName(undefined);
            }
        };
        loadField();
    }, [bridgeTarget, pageViewContext?.page]);
    // Hide the picture editor overlay when the pointer leaves the iframe area
    // or when interacting elsewhere in the app. This prevents the buttons from
    // staying visible after rapidly exiting the iframe or switching pages.
    useEffect(() => {
        if (!iframe)
            return;
        const hideOverlay = () => {
            if (!activeBridgeTargetRef.current)
                return;
            // Don't hide if a dialog or menu is open
            if (isDialogOpenRef.current)
                return;
            setBridgeTarget(undefined);
            setField(undefined);
            setVariantName(undefined);
        };
        const handlePointerEvent = (event) => {
            if (!activeBridgeTargetRef.current)
                return;
            // Don't hide if a dialog (e.g., crop dialog) is open
            if (isDialogOpenRef.current)
                return;
            const iframeRect = iframe.getBoundingClientRect();
            const isInsideIframe = event.clientX >= iframeRect.left &&
                event.clientX <= iframeRect.right &&
                event.clientY >= iframeRect.top &&
                event.clientY <= iframeRect.bottom;
            // Check if mouse is over a dropdown menu (rendered via portal outside iframe)
            const target = event.target;
            const isOverDropdownMenu = target?.closest('[data-slot="dropdown-menu-content"]') !== null;
            if (!isInsideIframe && !isOverDropdownMenu) {
                hideOverlay();
            }
        };
        window.addEventListener("mousemove", handlePointerEvent, true);
        window.addEventListener("mousedown", handlePointerEvent, true);
        window.addEventListener("blur", hideOverlay);
        return () => {
            window.removeEventListener("mousemove", handlePointerEvent, true);
            window.removeEventListener("mousedown", handlePointerEvent, true);
            window.removeEventListener("blur", hideOverlay);
        };
    }, [iframe]);
    if (editContext?.dragObject || !field || !bounds)
        return null;
    if (field.type === "picture" && !variantName)
        return null;
    const style = {
        left: bounds.x + "px",
        top: bounds.y + "px",
        width: bounds.width + "px",
        height: bounds.height + "px",
    };
    const forwardWheelToBridge = (e) => {
        return (pageViewContext?.requestBridgeScrollBy?.({
            x: e.deltaX,
            y: e.deltaY,
            behavior: "instant",
        }) ?? false);
    };
    const handleContextMenu = async (e) => {
        e.preventDefault();
        e.stopPropagation();
        if (!pageViewContext?.page || !editContext)
            return;
        try {
            await editContext.setFocusedField(field.descriptor, false);
        }
        catch { }
        const selectedComponents = editContext
            .getSelection()
            .map((id) => getComponentById(id, pageViewContext.page))
            .filter((x) => x);
        const targetComponents = selectedComponents.length
            ? selectedComponents
            : (() => {
                const targetId = bridgeTarget?.componentId || field.descriptor.item.id;
                const comp = getComponentById(targetId, pageViewContext.page);
                return comp ? [comp] : [];
            })();
        if (editContext.showLayoutComponents === false &&
            targetComponents.some((c) => c.layoutId)) {
            return;
        }
        const fieldButtons = await loadFieldButtons(field.descriptor);
        const showMenu = await showComponentContextMenu(targetComponents, editContext, field.descriptor, fieldButtons);
        if (showMenu)
            showMenu(e);
    };
    if (field.type === "image") {
        return (_jsx(ImageEditor, { field: field, style: style, forwardScrollevents: true, isPageEditor: true, onDialogOpenChange: setIsDialogOpen, onContextMenu: handleContextMenu, onForwardWheel: forwardWheelToBridge }));
    }
    return (_jsx(PictureEditor, { field: field, variantName: variantName, style: style, forwardScrollevents: true, onForwardWheel: forwardWheelToBridge, isPageEditor: true, onDialogOpenChange: setIsDialogOpen, onContextMenu: handleContextMenu }));
}
function getBridgePictureTarget(interaction, fallbackItem) {
    if (!interaction.media || !interaction.fieldId)
        return undefined;
    const item = bridgeItemToItemDescriptor(interaction.item, fallbackItem);
    if (!item)
        return undefined;
    return {
        elementKey: interaction.elementKey || interaction.media.elementKey,
        fieldId: interaction.fieldId,
        item,
        variantName: interaction.media.variantName,
        componentId: interaction.componentId,
    };
}
export function bridgeItemToItemDescriptor(item, fallbackItem) {
    if (!item?.id)
        return undefined;
    const descriptor = {
        id: item.id,
        language: item.language || fallbackItem?.language || "en",
        version: item.version ?? fallbackItem?.version ?? 0,
    };
    if (item.name)
        descriptor.name = item.name;
    if (item.displayName)
        descriptor.displayName = item.displayName;
    if (item.path)
        descriptor.path = item.path;
    if (item.database)
        descriptor.database = item.database;
    return descriptor;
}
function isEditableMediaField(field) {
    return (!!field &&
        typeof field === "object" &&
        "type" in field &&
        (field.type === "picture" ||
            field.type === "image"));
}
function bridgePictureTargetsEqual(left, right) {
    if (left === right)
        return true;
    if (!left || !right)
        return false;
    return (left.elementKey === right.elementKey &&
        left.fieldId === right.fieldId &&
        left.item.id === right.item.id &&
        left.item.language === right.item.language &&
        left.item.version === right.item.version &&
        left.variantName === right.variantName &&
        left.componentId === right.componentId);
}
//# sourceMappingURL=PictureEditorOverlay.js.map