import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useState } from "react";
import { useEditContext } from "../client/editContext";
import { useSlotContext } from "../views/editorSlotContext";
import { getVisibleInsertOptions } from "../insertMenuItems";
import { getAllPlaceholders } from "../componentTreeHelper";
import { findComponentRect } from "../utils";
import { PlaceholderDropZone } from "./PlaceholderDropZone";
export function PlaceholderDropZones({ scale, iframe, size, scroll, pageViewContext, }) {
    const [placeholders, setPlaceholders] = useState([]);
    const editContext = useEditContext();
    const slotContext = useSlotContext();
    const effectiveScroll = scroll ?? pageViewContext?.scroll ?? 0;
    useEffect(() => {
        if (!pageViewContext?.page)
            return;
        setPlaceholders(getAllPlaceholders(pageViewContext.page));
    }, [pageViewContext?.page]);
    // Only show PlaceholderDropZones for the active editor slot
    if (!slotContext?.isActive)
        return null;
    if (!pageViewContext ||
        (!editContext?.dragObject &&
            !editContext?.selectedForInsertion &&
            !editContext?.insertMode) ||
        !placeholders)
        return null;
    const showAllDueToInsertMode = !!editContext?.insertMode &&
        !editContext?.dragObject &&
        !editContext?.selectedForInsertion;
    const hasVisibleInsertOptions = (placeholder) => getVisibleInsertOptions(placeholder.insertOptions).length > 0;
    const matchingPlaceholders = (showAllDueToInsertMode ? placeholders : placeholders)
        // When layout components are hidden/disabled, exclude placeholders inside layout components
        .filter((x) => editContext?.showLayoutComponents === true ||
        !isInsideLayoutComponent(x.parentComponent))
        .filter((x) => {
        const visibleInsertOptions = getVisibleInsertOptions(x.insertOptions);
        return (
        // Only include editable placeholders
        x.editable &&
            hasVisibleInsertOptions(x) &&
            (showAllDueToInsertMode ||
                x.parentComponent?.id === editContext.selectedForInsertion ||
                visibleInsertOptions.find((y) => y.typeId === editContext.selectedForInsertion ||
                    y.typeId === editContext.dragObject?.typeId ||
                    y.typeId === editContext.dragObject?.templateId ||
                    y.compatibleTypeIds?.find((z) => z == editContext.dragObject?.typeId) !== undefined ||
                    y.typeId === editContext.dragObject?.templateId ||
                    y.compatibleTypeIds?.find((z) => z == editContext.dragObject?.templateId) !== undefined)));
    });
    if (!iframe)
        return;
    const zones = [];
    const scrollHeight = pageViewContext?.editorIframe?.contentWindow?.document?.documentElement
        ?.scrollHeight || 0;
    matchingPlaceholders.forEach((placeholder) => {
        const iframeBody = iframe?.contentWindow?.document?.body;
        if (!iframeBody)
            return;
        let placeholderElement = iframeBody.querySelector("[data-placeholder-start='" + placeholder.key + "']");
        let isUsingParentBounds = false;
        if (!placeholderElement && placeholder.components.length > 0) {
            // Query from the passed iframe to ensure we get elements from the correct document (important for minimap)
            const firstComponent = placeholder.components[0];
            placeholderElement =
                iframeBody.querySelector("[data-component-start='" + firstComponent?.id + "']")?.nextElementSibling || firstComponent?.firstDOMElement || null;
        }
        // For empty placeholders, use parent component bounds as last resort
        if (!placeholderElement && placeholder.parentComponent) {
            // Query from the passed iframe to ensure we get elements from the correct document (important for minimap)
            placeholderElement =
                iframeBody.querySelector("[data-component-start='" + placeholder.parentComponent.id + "']")?.nextElementSibling || placeholder.parentComponent.firstDOMElement || null;
            isUsingParentBounds = true;
        }
        if (!placeholderElement)
            return;
        const zoom = pageViewContext.zoom;
        let position;
        let anchor = "top";
        let index = 0;
        const description = placeholderElement.getAttribute("data-description");
        let referenceElement;
        let orientation = null;
        // Special handling for empty placeholders using parent bounds
        if (isUsingParentBounds) {
            const rect = placeholderElement.getBoundingClientRect();
            // Center the drop zone in the middle of the parent
            position = {
                x: (rect.x + rect.width / 2) * zoom,
                y: (rect.y + rect.height / 2) * zoom,
            };
            anchor = "top"; // Default anchor for centered position
            referenceElement = placeholderElement;
            orientation = "vertical"; // Default for centered placeholders
        }
        else {
            // Original positioning logic for normal placeholders
            const prev = getPreviousElement(placeholderElement);
            const nextOrParent = getNextElement(placeholderElement) || placeholderElement.parentElement;
            orientation = placeholderElement?.getAttribute("data-orientation");
            if (!orientation)
                orientation = detectOrientation(placeholderElement, placeholder.components);
            const rect = (prev ?? nextOrParent).getBoundingClientRect();
            position =
                orientation === "horizontal"
                    ? {
                        x: (prev ? rect.x + rect.width : rect.x) * zoom,
                        y: (rect.y + rect.height / 2) * zoom,
                    }
                    : {
                        x: (rect.x + rect.width / 2) * zoom,
                        y: (prev ? rect.y + rect.height : rect.y) * zoom,
                    };
            if (prev && orientation === "horizontal") {
                anchor = "right";
            }
            if (prev && orientation !== "horizontal") {
                anchor = "bottom";
            }
            if (!prev && orientation === "horizontal") {
                anchor = "left";
            }
            if (!prev && orientation !== "horizontal") {
                anchor = "top";
            }
            referenceElement = prev ?? nextOrParent;
        }
        zones.push({
            placeholder,
            position,
            index,
            element: referenceElement,
            anchor,
            description,
        });
        placeholder.components.forEach((component) => {
            const componentRect = findComponentRect(iframe, component);
            if (!componentRect)
                return;
            const position = getPositionFromRect(componentRect.rect, pageViewContext.zoom, orientation);
            index++;
            zones.push({
                placeholder,
                position,
                index,
                anchor: orientation === "horizontal" ? "right" : "bottom",
                element: componentRect.elements[componentRect.elements.length - 1],
            });
        });
        //   let nextElement = placeholderElement?.nextElementSibling;
        //   while (nextElement) {
        //     nextElement = nextElement?.nextElementSibling;
        //     if (nextElement) {
        //       if (
        //         nextElement.getAttribute("data-placeholder-end") === placeholder.key
        //       ) {
        //         break;
        //       }
        //       if (nextElement.getAttribute("data-component-end")) {
        //         const componentRect = findComponentRect(
        //           iframe,
        //           (nextElement.getAttribute("data-component-end") ||
        //             nextElement.getAttribute("data-dropzone"))!,
        //         );
        //         if (!componentRect) continue;
        //         const position = getPositionFromRect(
        //           componentRect.rect,
        //           pageViewContext.zoom,
        //           orientation,
        //         );
        //         index++;
        //         zones.push({
        //           placeholder,
        //           position,
        //           index,
        //           anchor: orientation === "horizontal" ? "right" : "bottom",
        //           element: componentRect.elements[componentRect.elements.length - 1]!,
        //         });
        //       } else if (nextElement.getAttribute("data-dropzone")) {
        //         const rect = nextElement.getBoundingClientRect();
        //         const position = getPositionFromRect(rect, pageViewContext.zoom);
        //         index++;
        //         zones.push({
        //           placeholder,
        //           position,
        //           index,
        //           anchor: orientation === "horizontal" ? "left" : "top",
        //           element: nextElement,
        //         });
        //       }
        //     }
        //   }
    });
    // Always hide zones before the first layout component in a placeholder
    const zonesWithoutBeforeFirstLayout = zones.filter((z) => {
        const components = z.placeholder.components;
        const firstLayoutIndex = components.findIndex((c) => !!c.layoutId);
        if (firstLayoutIndex >= 0 && z.index <= firstLayoutIndex) {
            return false;
        }
        return true;
    });
    // When layout components are hidden, remove zones that are between two layout components
    const filteredZones = editContext?.showLayoutComponents === false
        ? zonesWithoutBeforeFirstLayout.filter((z) => {
            const components = z.placeholder.components;
            if (z.index >= 1 && z.index < components.length) {
                const prev = components[z.index - 1];
                const next = components[z.index];
                if (prev?.layoutId && next?.layoutId)
                    return false;
            }
            return true;
        })
        : zonesWithoutBeforeFirstLayout;
    // Track used positions to detect and offset overlapping dropzones
    const usedPositions = new Map();
    const DROPZONE_SIZE = 32; // Size of the dropzone button (h-8 w-8 = 32px)
    const OVERLAP_THRESHOLD = DROPZONE_SIZE; // Distance threshold for considering positions as overlapping
    return filteredZones.map((zone, index) => {
        let x = Math.min(pageViewContext.viewport.width - 20, Math.max(20, zone.position.x * (scale || 1)));
        let y = Math.min(scrollHeight - 20, Math.max(20 - effectiveScroll, zone.position.y * (scale || 1)));
        // Create a position key for detecting overlaps (rounded to threshold)
        const posKey = `${Math.round(x / OVERLAP_THRESHOLD)}_${Math.round(y / OVERLAP_THRESHOLD)}`;
        const overlapCount = usedPositions.get(posKey) || 0;
        // If this position is already used, offset the dropzone
        if (overlapCount > 0) {
            // Spread overlapping dropzones in a horizontal row
            x = x + overlapCount * (DROPZONE_SIZE + 8);
            // Ensure we don't go off-screen
            if (x > pageViewContext.viewport.width - 20) {
                // Wrap to next row if needed
                x = 20 + ((overlapCount - 1) % 5) * (DROPZONE_SIZE + 8);
                y = y + Math.floor((overlapCount - 1) / 5) * (DROPZONE_SIZE + 8);
            }
        }
        usedPositions.set(posKey, overlapCount + 1);
        const components = zone.placeholder.components;
        const prevComponent = zone.index >= 1 ? components[zone.index - 1] : null;
        const nextComponent = zone.index < components.length ? components[zone.index] : null;
        const isAdjacentToLayout = !!prevComponent?.layoutId || !!nextComponent?.layoutId;
        const isInsideLayout = isInsideLayoutComponent(zone.placeholder.parentComponent);
        const isLayoutZone = isInsideLayout || isAdjacentToLayout;
        // Calculate the page-component-only index by counting only non-layout components before this position
        const adjustedIndex = zone.placeholder.components
            .slice(0, zone.index)
            .filter((c) => !c.layoutId).length;
        return (_jsx(PlaceholderDropZone, { placeholder: zone.placeholder, spotPosition: {
                x,
                y,
            }, index: adjustedIndex, size: size, spotPositionElement: zone.element, spotPositionAnchor: zone.anchor, parentName: zone.placeholder.parentComponent?.name, description: zone.description || undefined, isLayoutZone: isLayoutZone }, index));
    });
}
function getPreviousElement(element) {
    let prev = element.previousElementSibling;
    while (prev && prev.tagName === "SCRIPT") {
        prev = prev.previousElementSibling;
    }
    return prev;
}
function getNextElement(element) {
    let next = element.nextElementSibling;
    while (next && next.tagName === "SCRIPT") {
        next = next.nextElementSibling;
    }
    return next;
}
function getPositionFromRect(rect, zoom, orientation) {
    const position = orientation === "horizontal"
        ? {
            x: rect.x + rect.width * zoom,
            y: (rect.y + rect.height / 2) * zoom,
        }
        : {
            x: (rect.x + rect.width / 2) * zoom,
            y: rect.y + rect.height * zoom,
        };
    return position;
}
function detectOrientation(placeholderElement, components) {
    // Check parent element for flex/grid direction
    const parentElement = placeholderElement.parentElement;
    if (parentElement) {
        const parentStyle = window.getComputedStyle(parentElement);
        const display = parentStyle.getPropertyValue("display");
        // Check for flex direction
        if (display === "flex" || display === "inline-flex") {
            const flexDirection = parentStyle.getPropertyValue("flex-direction");
            if (flexDirection === "row" || flexDirection === "row-reverse") {
                return "horizontal";
            }
            if (flexDirection === "column" || flexDirection === "column-reverse") {
                return "vertical";
            }
        }
        // Check for grid layout
        if (display === "grid" || display === "inline-grid") {
            const gridAutoFlow = parentStyle.getPropertyValue("grid-auto-flow");
            if (gridAutoFlow.includes("column")) {
                return "horizontal";
            }
            if (gridAutoFlow.includes("row")) {
                return "vertical";
            }
        }
    }
    // Analyze sibling positions if available
    if (components.length > 1) {
        const prevRect = components[0]?.firstDOMElement?.getBoundingClientRect();
        const nextRect = components[1]?.firstDOMElement?.getBoundingClientRect();
        if (!prevRect || !nextRect)
            return "horizontal";
        // Compare the position differences
        const horizontalDiff = Math.abs(nextRect.x - prevRect.x);
        const verticalDiff = Math.abs(nextRect.y - prevRect.y);
        // If horizontal difference is greater, it's likely a horizontal layout
        return horizontalDiff > verticalDiff ? "horizontal" : "vertical";
    }
    // Default to vertical if we can't determine
    return "vertical";
}
function isInsideLayoutComponent(component) {
    let current = component;
    while (current) {
        if (current.layoutId)
            return true;
        current = current.parentPlaceholder?.parentComponent;
    }
    return false;
}
//# sourceMappingURL=PlaceholderDropZones.js.map