import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useEffect, useRef, useState } from "react";
import { useEditContext } from "../client/editContext";
import { PictureEditor } from "../PictureEditor";
import { getComponentById } from "../componentTreeHelper";
import { showComponentContextMenu } from "../ContextMenu";
import { loadFieldButtons } from "../services/editService";
import { measureElementRect, rectEquals, } from "./overlay/geometry";
import { getAccessibleIframeDocument, getAccessibleIframeWindow, } from "./overlay/iframeAccess";
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 [element, setElement] = useState();
    const activeElementRef = 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]);
    const onMouseEnter = useCallback((e) => {
        if (isDialogOpenRef.current)
            return;
        if (!e.target)
            return;
        if (!("closest" in e.target))
            return;
        const target = e.target;
        const pictureElement = target.closest("picture") || target.closest("img");
        setElement(pictureElement || undefined);
    }, [iframe, editContext]);
    useEffect(() => {
        activeElementRef.current = element || undefined;
    }, [element]);
    const bounds = useOverlayMeasurement((metrics) => (element ? measureElementRect(element, metrics) : null), [element], {
        initialValue: null,
        equals: rectEquals,
        interests: ["viewport", "layout", "text", "adornment-data"],
    });
    useEffect(() => {
        const loadField = async () => {
            if (element) {
                const itemId = element.getAttribute("data-itemid");
                const language = element.getAttribute("data-language");
                const version = element.getAttribute("data-version");
                const fieldId = element.getAttribute("data-fieldid");
                if (!itemId ||
                    !language ||
                    !version ||
                    !fieldId ||
                    !pageViewContext?.page ||
                    !getAccessibleIframeWindow(iframe))
                    return;
                const component = getComponentById(itemId, pageViewContext.page);
                if (component == null)
                    return;
                // Guard: if layout components are hidden, do not show picture editor overlay for layout components
                if (editContextRef.current?.showLayoutComponents === false &&
                    component.layoutId) {
                    setField(undefined);
                    setVariantName(undefined);
                    setElement(undefined);
                    return;
                }
                const item = await editContext.itemsRepository.getItem(component.datasourceItem);
                const pictureField = item?.fields.find((f) => f.id === fieldId);
                if (!pictureField)
                    return;
                setField(pictureField);
            }
            else {
                setField(undefined);
            }
        };
        loadField();
    }, [element, 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 (!activeElementRef.current)
                return;
            // Don't hide if a dialog or menu is open
            if (isDialogOpenRef.current)
                return;
            setElement(undefined);
            setField(undefined);
            setVariantName(undefined);
        };
        const handlePointerEvent = (event) => {
            if (!activeElementRef.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]);
    useEffect(() => {
        const iframeWindow = getAccessibleIframeWindow(iframe);
        if (!element || !iframeWindow)
            return;
        const sourceELement = getCurrentPictureSource(element, iframeWindow);
        if (sourceELement) {
            const variantName = sourceELement.getAttribute("data-variant");
            if (variantName) {
                setVariantName(variantName);
            }
        }
    }, [pageViewContext?.viewport, element]);
    const handleLoad = useCallback(() => {
        getAccessibleIframeDocument(iframe)?.addEventListener("mouseenter", onMouseEnter, true);
    }, [iframe, onMouseEnter]);
    useEffect(() => {
        if (iframe) {
            // If the iframe is already loaded, attach the listener immediately
            const iframeDocument = getAccessibleIframeDocument(iframe);
            if (iframeDocument?.readyState === "complete" ||
                iframeDocument?.readyState === "interactive") {
                handleLoad();
            }
            iframe.addEventListener("load", handleLoad);
            return () => {
                const iframeDocument = getAccessibleIframeDocument(iframe);
                if (iframeDocument) {
                    iframeDocument.removeEventListener("mouseenter", onMouseEnter, true);
                }
                if (iframe) {
                    iframe.removeEventListener("load", handleLoad);
                }
            };
        }
    }, [iframe, editContext?.refreshCompletedFlag, handleLoad]);
    if (!field || !variantName || !element || !bounds)
        return null;
    const style = {
        left: bounds.x + "px",
        top: bounds.y + "px",
        width: bounds.width + "px",
        height: bounds.height + "px",
    };
    return (_jsx(PictureEditor, { field: field, variantName: variantName, style: style, forwardScrollevents: true, isPageEditor: true, onDialogOpenChange: setIsDialogOpen, onContextMenu: async (e) => {
            e.preventDefault();
            e.stopPropagation();
            if (!pageViewContext?.page || !editContext)
                return;
            // Focus the picture field so Add Comment associates with it
            try {
                await editContext.setFocusedField(field.descriptor, false);
            }
            catch { }
            // Determine target components: prefer current selection, fallback to hovered element's component
            const selectedComponents = (editContext.selection || [])
                .map((id) => getComponentById(id, pageViewContext.page))
                .filter((x) => x);
            const targetComponents = selectedComponents.length
                ? selectedComponents
                : (() => {
                    const itemId = element?.getAttribute("data-itemid");
                    if (!itemId)
                        return [];
                    const comp = getComponentById(itemId, 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);
        } }));
}
function getCurrentPictureSource(pictureElement, iframeWindow) {
    if (pictureElement.tagName === "IMG")
        return pictureElement;
    const sources = pictureElement.querySelectorAll("source");
    let currentSrc = null;
    sources.forEach((source) => {
        const media = source.getAttribute("media");
        if (!media)
            return;
        if (media && iframeWindow.matchMedia(media).matches) {
            currentSrc = source;
        }
    });
    return currentSrc || pictureElement.querySelector("img") || null;
}
//# sourceMappingURL=PictureEditorOverlay.js.map