import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useCallback, useEffect, useRef, useState } from "react";
import ContentTree from "../ContentTree";
import { TreeSettingsMenu } from "../content-tree/TreeSettingsMenu";
import { useEditContext } from "../client/editContext";
import { getInsertOptionsForCurrentSelection } from "../utils/insertOptions";
import ItemSearch from "../ui/ItemSearch";
import { GutterProvider, GutterColumns, useGutterContextSafe, } from "../tree-indicators";
/** Width of each gutter column in pixels */
const GUTTER_COLUMN_WIDTH = 18;
/**
 * Inner component that can access gutter context to determine tree padding.
 */
function MainContentTreeInner({ mode, rootItemIds, selectedItem, shouldScrollToSelected, selectedItemIds, setShouldScrollToSelected, setSelectedItemIds, editContext, isDraggable, hideRootNodes, currentLanguage, onTreeItemClick, }) {
    const gutterContext = useGutterContextSafe();
    // Don't show indicators in insert-component mode
    const showIndicators = mode !== "insert-component";
    const visibleGutterCount = showIndicators && gutterContext?.visibleGutters.length
        ? gutterContext.visibleGutters.length
        : 0;
    const gutterPadding = visibleGutterCount > 0 ? visibleGutterCount * GUTTER_COLUMN_WIDTH + 8 : 0;
    return (_jsx("div", { className: "relative flex-1", "data-testid": "main-content-tree", children: _jsx("div", { className: "absolute inset-1 overflow-auto", children: _jsx("div", { className: "h-full", style: { paddingLeft: gutterPadding }, children: _jsx(ContentTree, { enableDragAndDrop: mode == "normal" || mode === "insert-component", language: currentLanguage, rootItemIds: rootItemIds, expandIdPath: selectedItem?.idPath
                        ? selectedItem?.idPath.split("/").slice(0, -1).join("/")
                        : undefined, scrollToSelected: shouldScrollToSelected, className: "h-full", selectPagesOnly: mode === "select-page", selectionMode: mode == "insert-component" ? "none" : "multiple", selectedItemIds: selectedItemIds, onSelectionChange: (selection) => {
                        if (mode === "insert-component")
                            return;
                        const selectedItems = selection;
                        const selectedIds = selectedItems.map((x) => x.id);
                        setShouldScrollToSelected(false);
                        setSelectedItemIds(selectedIds);
                        editContext.setContentTreeSelection(selectedIds);
                    }, onItemClick: (item, ev) => {
                        if (mode !== "normal")
                            return;
                        // Mark this as a tree click BEFORE loading the item
                        // This prevents the scroll effect from triggering for visible items
                        onTreeItemClick(item.id);
                        // Ctrl is reserved for multi-selection in the tree.
                        // Use Alt-click (power gesture) or middle-click (primary gesture) to open in a new slot.
                        const openInNewSlot = !!(ev?.altKey || ev?.button === 1);
                        editContext.loadItem({ id: item.id, language: item.language, version: 0 }, { openInNewSlot });
                    }, onDoubleClick: (item) => {
                        if (mode !== "normal")
                            return;
                        // Mark this as a tree click BEFORE loading the item
                        onTreeItemClick(item.id);
                        editContext.loadItem({
                            id: item.id,
                            language: item.language,
                            version: 0,
                        });
                    }, showGrabCursorForDraggableNodes: mode === "insert-component", isDraggable: isDraggable, enableContextMenu: mode === "normal", hideRootNodes: hideRootNodes, renderNodePrefix: (node, depth) => showIndicators && node.data?.id ? (_jsx(GutterColumns, { itemId: node.data.id, itemLanguage: currentLanguage, depth: depth })) : null }) }) }) }));
}
export function MainContentTree({ mode, rootItemId, hideRootNodes, }) {
    const editContext = useEditContext();
    const [insertOptions, setInsertOptions] = useState();
    if (!editContext)
        return null;
    const page = editContext.page;
    const selectedItem = editContext.item ?? page?.item;
    const activeSlotId = editContext.activeSlotId;
    const [selectedItemIds, setSelectedItemIds] = useState([]);
    const [rootItemIds, setRootItemIds] = useState([
        rootItemId ?? "{11111111-1111-1111-1111-111111111111}",
    ]);
    // Track whether selection change is programmatic (should scroll) or manual (should not scroll)
    const [shouldScrollToSelected, setShouldScrollToSelected] = useState(false);
    // Track the last item we scrolled to, to avoid unnecessary re-scrolls
    const lastScrolledItemRef = useRef(null);
    // Track the last active slot to detect slot switches
    const lastActiveSlotRef = useRef(null);
    // Track when a click originated from within the tree - these should NOT trigger scroll
    const treeClickInProgressRef = useRef(null);
    // Called when user clicks an item in the tree - marks that the upcoming selection
    // change should NOT trigger a scroll (since the item is already visible)
    const handleTreeItemClick = useCallback((itemId) => {
        treeClickInProgressRef.current = itemId;
    }, []);
    const isDraggable = useCallback((item) => {
        // Only allow dragging in insert-component mode
        if (mode !== "insert-component") {
            return true;
        }
        if (!insertOptions)
            return false;
        // Check if the item's template is compatible with any insert option
        return insertOptions.some((insertOption) => {
            // Direct type match
            if (insertOption.typeId === item.templateId) {
                return true;
            }
            // Compatible type match
            return (insertOption.compatibleTypeIds?.some((compatibleTypeId) => compatibleTypeId === item.templateId) ?? false);
        });
    }, [mode, insertOptions]);
    // Scroll to selected item when:
    // 1. The selected item changes from an EXTERNAL source (not from clicking in tree)
    // 2. The active slot changes (e.g., user switches between editor slots)
    // DO NOT scroll when user clicks an item that's already visible in the tree
    useEffect(() => {
        if (selectedItem) {
            // Check if this change came from a click within the tree
            const wasTreeClick = treeClickInProgressRef.current === selectedItem.id;
            if (wasTreeClick) {
                // Clear the flag and don't scroll - the item was clicked in the tree
                // so it's already visible
                treeClickInProgressRef.current = null;
                lastScrolledItemRef.current = selectedItem.id;
                lastActiveSlotRef.current = activeSlotId;
                setSelectedItemIds([selectedItem.id]);
                return;
            }
            // Detect if this is a slot switch (active slot changed but item might be same)
            const isSlotSwitch = activeSlotId !== lastActiveSlotRef.current && activeSlotId !== null;
            lastActiveSlotRef.current = activeSlotId;
            // Only scroll if:
            // - The selected item is different from last time we scrolled, OR
            // - The active slot changed (user switched to a different editor slot)
            const shouldScroll = selectedItem.id !== lastScrolledItemRef.current || isSlotSwitch;
            if (shouldScroll) {
                lastScrolledItemRef.current = selectedItem.id;
                // Mark this as a programmatic selection change (should scroll)
                setShouldScrollToSelected(true);
                setSelectedItemIds([selectedItem.id]);
                // Only sync selection if it's empty or the selected item is not in current selection
                // This prevents overwriting multi-selection when user has selected multiple items
                const currentSelection = editContext.contentTreeSelection || [];
                if (currentSelection.length === 0 ||
                    !currentSelection.includes(selectedItem.id)) {
                    editContext.setContentTreeSelection([selectedItem.id]);
                }
                // Reset the scroll flag after a generous delay.
                // The PerfectTree component uses a ref-based approach that won't be canceled by this reset.
                // This reset just ensures we don't continuously try to scroll on every re-render.
                const timeoutId = setTimeout(() => {
                    setShouldScrollToSelected(false);
                }, 1000);
                return () => clearTimeout(timeoutId);
            }
            else {
                // Item didn't change, just update the selection IDs without scrolling
                setSelectedItemIds([selectedItem.id]);
            }
        }
    }, [selectedItem?.id, activeSlotId]);
    useEffect(() => {
        setRootItemIds([rootItemId ?? "{11111111-1111-1111-1111-111111111111}"]);
    }, [rootItemId]);
    useEffect(() => {
        const loadInsertOptions = async () => {
            if (!page)
                return;
            const options = await getInsertOptionsForCurrentSelection(editContext);
            setInsertOptions(options);
        };
        loadInsertOptions();
    }, [editContext.selection, page]);
    // Use actual language and version from loaded item (contentEditorItem), not from descriptor
    // This ensures we use resolved values, not "0" which means "latest"
    const currentLanguage = editContext.item?.language ??
        editContext.currentItemDescriptor?.language ??
        "en";
    const currentVersion = editContext.item?.version ?? 1;
    return (_jsx(GutterProvider, { language: currentLanguage, version: currentVersion, children: _jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: `flex items-center gap-2 ${mode === "insert-component" ? "p-4" : "border-b border-gray-200 p-2"}`, children: [_jsx("div", { className: "flex-1", children: _jsx(ItemSearch, { resultClassName: "px-2 py-1", itemSelected: (item) => editContext?.loadItem({
                                    id: item.id,
                                    language: item.language,
                                    version: 0,
                                }) }) }), mode !== "insert-component" && _jsx(TreeSettingsMenu, {})] }), _jsx(MainContentTreeInner, { mode: mode, rootItemIds: rootItemIds, selectedItem: selectedItem, shouldScrollToSelected: shouldScrollToSelected, selectedItemIds: selectedItemIds, setShouldScrollToSelected: setShouldScrollToSelected, setSelectedItemIds: setSelectedItemIds, editContext: editContext, isDraggable: isDraggable, hideRootNodes: hideRootNodes, currentLanguage: currentLanguage, onTreeItemClick: handleTreeItemClick })] }) }));
}
//# sourceMappingURL=MainContentTree.js.map