"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompositionSelector = exports.useCompositionNavigation = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const studio_shared_1 = require("@remotion/studio-shared");
const react_1 = require("react");
const remotion_1 = require("remotion");
const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
const client_id_1 = require("../helpers/client-id");
const colors_1 = require("../helpers/colors");
const create_folder_tree_1 = require("../helpers/create-folder-tree");
const persist_open_folders_1 = require("../helpers/persist-open-folders");
const sort_by_nonce_history_1 = require("../helpers/sort-by-nonce-history");
const use_keybinding_1 = require("../helpers/use-keybinding");
const modals_1 = require("../state/modals");
const z_index_1 = require("../state/z-index");
const CompositionSelectorItem_1 = require("./CompositionSelectorItem");
const ContextMenu_1 = require("./ContextMenu");
const InitialCompositionLoader_1 = require("./InitialCompositionLoader");
const NotificationCenter_1 = require("./Notifications/NotificationCenter");
const actions_1 = require("./RenderQueue/actions");
const root_composition_menu_items_1 = require("./root-composition-menu-items");
const useCompositionNavigation = () => {
    const { compositions, canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
    const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
    const navigateToNextComposition = (0, react_1.useCallback)(() => {
        if (!canvasContent ||
            canvasContent.type !== 'composition' ||
            compositions.length <= 1) {
            return;
        }
        const currentIndex = compositions.findIndex((c) => c.id === canvasContent.compositionId);
        if (currentIndex === -1) {
            return;
        }
        const nextIndex = (currentIndex + 1) % compositions.length;
        const nextComposition = compositions[nextIndex];
        selectComposition(nextComposition, true);
    }, [canvasContent, compositions, selectComposition]);
    const navigateToPreviousComposition = (0, react_1.useCallback)(() => {
        if (!canvasContent ||
            canvasContent.type !== 'composition' ||
            compositions.length <= 1) {
            return;
        }
        const currentIndex = compositions.findIndex((c) => c.id === canvasContent.compositionId);
        if (currentIndex === -1) {
            return;
        }
        const previousIndex = (currentIndex - 1 + compositions.length) % compositions.length;
        const previousComposition = compositions[previousIndex];
        selectComposition(previousComposition, true);
    }, [canvasContent, compositions, selectComposition]);
    return (0, react_1.useMemo)(() => ({
        navigateToNextComposition,
        navigateToPreviousComposition,
    }), [navigateToNextComposition, navigateToPreviousComposition]);
};
exports.useCompositionNavigation = useCompositionNavigation;
const container = {
    display: 'flex',
    flexDirection: 'column',
    flex: 1,
    overflow: 'hidden',
    backgroundColor: colors_1.BACKGROUND,
};
const quickSwitcherArea = {
    padding: '4px 12px',
    borderBottom: `1px solid ${colors_1.BLACK_HEX}`,
};
const quickSwitcherTrigger = {
    backgroundColor: colors_1.WHITE_ALPHA_06,
    borderRadius: 5,
    padding: '4px 10px',
    color: colors_1.LIGHT_TEXT,
    fontSize: 12,
    cursor: 'pointer',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    border: 'none',
    width: '100%',
    appearance: 'none',
};
const shortcutLabel = {
    fontSize: 11,
    opacity: 0.6,
};
const autoScrollThreshold = 70;
const maxAutoScrollSpeed = 18;
const getAutoScrollSpeed = ({ clientY, element, }) => {
    const { top, bottom } = element.getBoundingClientRect();
    const threshold = Math.min(autoScrollThreshold, element.clientHeight / 2);
    if (threshold <= 0) {
        return 0;
    }
    const distanceToTop = clientY - top;
    const distanceToBottom = bottom - clientY;
    if (distanceToTop < threshold) {
        const progress = Math.min(1, (threshold - distanceToTop) / threshold);
        return -Math.ceil(progress * maxAutoScrollSpeed);
    }
    if (distanceToBottom < threshold) {
        const progress = Math.min(1, (threshold - distanceToBottom) / threshold);
        return Math.ceil(progress * maxAutoScrollSpeed);
    }
    return 0;
};
const CompositionSelector = () => {
    const { compositions, canvasContent, folders } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
    const { foldersExpanded } = (0, react_1.useContext)(persist_open_folders_1.ExpandedFoldersContext);
    const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
    const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
        .previewServerState.type;
    const rootContextMenuItems = (0, react_1.useMemo)(() => {
        return (0, root_composition_menu_items_1.getRootCompositionMenuItems)({
            connectionStatus,
            readOnlyStudio: window.remotion_isReadOnlyStudio,
            setSelectedModal,
        });
    }, [connectionStatus, setSelectedModal]);
    const [rootDragHovered, setRootDragHovered] = (0, react_1.useState)(false);
    const listRef = (0, react_1.useRef)(null);
    const autoScrollAnimation = (0, react_1.useRef)(null);
    const autoScrollSpeed = (0, react_1.useRef)(0);
    const { tabIndex } = (0, z_index_1.useZIndex)();
    const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
    const sortedCompositions = (0, react_1.useMemo)(() => {
        return (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(compositions);
    }, [compositions]);
    const sortedFolders = (0, react_1.useMemo)(() => {
        return (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(folders);
    }, [folders]);
    const items = (0, react_1.useMemo)(() => {
        return (0, create_folder_tree_1.createFolderTree)(sortedCompositions, sortedFolders, foldersExpanded);
    }, [sortedCompositions, sortedFolders, foldersExpanded]);
    const list = (0, react_1.useMemo)(() => {
        return {
            flex: 1,
            overflowY: 'auto',
            backgroundColor: rootDragHovered ? colors_1.WHITE_ALPHA_12 : colors_1.BACKGROUND,
        };
    }, [rootDragHovered]);
    const toggleFolder = (0, react_1.useCallback)((folderName, parentName) => {
        var _a;
        (_a = remotion_1.Internals.compositionSelectorRef.current) === null || _a === void 0 ? void 0 : _a.toggleFolder(folderName, parentName);
    }, []);
    const openQuickSwitcher = (0, react_1.useCallback)(() => {
        setSelectedModal({
            type: 'quick-switcher',
            mode: 'compositions',
            invocationTimestamp: Date.now(),
        });
    }, [setSelectedModal]);
    const clearRootDragHover = (0, react_1.useCallback)(() => {
        setRootDragHovered(false);
    }, []);
    const stopCompositionListAutoScroll = (0, react_1.useCallback)(() => {
        autoScrollSpeed.current = 0;
        if (autoScrollAnimation.current !== null) {
            cancelAnimationFrame(autoScrollAnimation.current);
            autoScrollAnimation.current = null;
        }
    }, []);
    const runCompositionListAutoScroll = (0, react_1.useCallback)(() => {
        const listElement = listRef.current;
        const speed = autoScrollSpeed.current;
        if (listElement === null || speed === 0) {
            autoScrollAnimation.current = null;
            return;
        }
        const scrollTopBefore = listElement.scrollTop;
        listElement.scrollTop += speed;
        if (listElement.scrollTop === scrollTopBefore) {
            autoScrollAnimation.current = null;
            return;
        }
        autoScrollAnimation.current = requestAnimationFrame(runCompositionListAutoScroll);
    }, []);
    const setCompositionListAutoScrollSpeed = (0, react_1.useCallback)((speed) => {
        if (speed === 0) {
            stopCompositionListAutoScroll();
            return;
        }
        autoScrollSpeed.current = speed;
        if (autoScrollAnimation.current === null) {
            autoScrollAnimation.current = requestAnimationFrame(runCompositionListAutoScroll);
        }
    }, [runCompositionListAutoScroll, stopCompositionListAutoScroll]);
    const onCompositionListDragOverCapture = (0, react_1.useCallback)((event) => {
        if (window.remotion_isReadOnlyStudio ||
            !Array.from(event.dataTransfer.types).includes(studio_shared_1.COMPOSITION_DRAG_MIME_TYPE)) {
            stopCompositionListAutoScroll();
            return;
        }
        const listElement = listRef.current;
        if (listElement === null) {
            stopCompositionListAutoScroll();
            return;
        }
        setCompositionListAutoScrollSpeed(getAutoScrollSpeed({ clientY: event.clientY, element: listElement }));
    }, [setCompositionListAutoScrollSpeed, stopCompositionListAutoScroll]);
    (0, react_1.useEffect)(() => {
        return stopCompositionListAutoScroll;
    }, [stopCompositionListAutoScroll]);
    const onRootDragOver = (0, react_1.useCallback)((event) => {
        if (window.remotion_isReadOnlyStudio ||
            !Array.from(event.dataTransfer.types).includes(studio_shared_1.COMPOSITION_DRAG_MIME_TYPE)) {
            return;
        }
        event.preventDefault();
        event.dataTransfer.dropEffect = 'move';
        setRootDragHovered(true);
    }, []);
    const onRootDragLeave = (0, react_1.useCallback)((event) => {
        const { relatedTarget } = event;
        if (relatedTarget instanceof Node &&
            event.currentTarget.contains(relatedTarget)) {
            return;
        }
        stopCompositionListAutoScroll();
        setRootDragHovered(false);
    }, [stopCompositionListAutoScroll]);
    const onRootDrop = (0, react_1.useCallback)(async (event) => {
        if (window.remotion_isReadOnlyStudio) {
            return;
        }
        const raw = event.dataTransfer.getData(studio_shared_1.COMPOSITION_DRAG_MIME_TYPE);
        const parsed = raw ? (0, studio_shared_1.parseCompositionDragData)(raw) : null;
        if (parsed === null) {
            return;
        }
        event.preventDefault();
        event.stopPropagation();
        stopCompositionListAutoScroll();
        setRootDragHovered(false);
        const composition = compositions.find((c) => c.id === parsed.compositionId);
        if (!composition || composition.folderName === null) {
            return;
        }
        const notification = (0, NotificationCenter_1.showNotification)(`Moving ${parsed.compositionId}...`, null);
        const controller = new AbortController();
        try {
            const result = await (0, actions_1.applyCodemod)({
                codemod: {
                    type: 'move-composition-to-folder',
                    idToMove: parsed.compositionId,
                    folderName: null,
                    parentName: null,
                },
                dryRun: false,
                signal: controller.signal,
                symbolicatedStack: (0, studio_shared_1.compositionDragDataToSymbolicatedStack)(parsed),
            });
            notification.replaceContent(result.success
                ? `Moved ${parsed.compositionId} outside of folder`
                : result.reason, result.success ? 2000 : 4000);
        }
        catch (err) {
            notification.replaceContent(err instanceof Error ? err.message : String(err), 4000);
        }
    }, [compositions, stopCompositionListAutoScroll]);
    return (jsx_runtime_1.jsxs("div", { style: container, children: [
            jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: listRef, values: rootContextMenuItems, onOpen: null }), jsx_runtime_1.jsx("div", { style: quickSwitcherArea, children: jsx_runtime_1.jsxs("button", { type: "button", style: quickSwitcherTrigger, onClick: openQuickSwitcher, tabIndex: tabIndex, children: ["Search...", (0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? null : (jsx_runtime_1.jsxs("span", { style: shortcutLabel, children: [ShortcutHint_1.cmdOrCtrlCharacter, "+K"] }))] }) }), jsx_runtime_1.jsx("div", { ref: listRef, className: "__remotion-vertical-scrollbar", style: list, onDragOverCapture: onCompositionListDragOverCapture, onDragEndCapture: stopCompositionListAutoScroll, onDragOver: onRootDragOver, onDragLeave: onRootDragLeave, onDropCapture: stopCompositionListAutoScroll, onDrop: onRootDrop, children: items.map((c) => {
                    return (jsx_runtime_1.jsx(CompositionSelectorItem_1.CompositionSelectorItem, { level: 0, currentComposition: canvasContent && canvasContent.type === 'composition'
                            ? canvasContent.compositionId
                            : null, selectComposition: selectComposition, toggleFolder: toggleFolder, clearRootDragHover: clearRootDragHover, tabIndex: tabIndex, item: c }, c.key + c.type));
                }) })
        ] }));
};
exports.CompositionSelector = CompositionSelector;
