// (C) 2022-2025 GoodData Corporation
import { useEffect, useState } from "react";
import { useDragDropManager } from "@evil-internetmann/react-dnd";
import { useInterval } from "./useInterval.js";
const SCROLLING_STEP = 3;
const SCROLLING_INTERVAL = 5;
const SCROLLING_ZONE_HEIGHT = 100;
const SCROLLING_ITEM_TYPES = [
    "insightListItem",
    "insight",
    "insight-placeholder",
    "kpi",
    "kpi-placeholder",
    "richText",
    "richTextListItem",
    "visualizationSwitcher",
    "visualizationSwitcherListItem",
    "dashboardLayout",
    "dashboardLayoutListItem",
    "internal-height-resizer",
];
var ScrollingDirection;
(function (ScrollingDirection) {
    ScrollingDirection[ScrollingDirection["Up"] = -1] = "Up";
    ScrollingDirection[ScrollingDirection["Down"] = 1] = "Down";
    ScrollingDirection[ScrollingDirection["None"] = 0] = "None";
})(ScrollingDirection || (ScrollingDirection = {}));
export function useDashboardDragScroll(contentRef, stickyHeaderRef, stickyFooterRef) {
    const [scrollingDirection, setScrollingDirection] = useState(ScrollingDirection.None);
    const dragDropManager = useDragDropManager();
    useEffect(() => {
        return dragDropManager.getMonitor().subscribeToOffsetChange(() => {
            const itemType = dragDropManager.getMonitor().getItemType();
            const clientOffset = dragDropManager.getMonitor().getSourceClientOffset();
            const initialClientOffset = dragDropManager.getMonitor().getInitialClientOffset();
            const initialSourceClientOffset = dragDropManager.getMonitor().getInitialSourceClientOffset();
            const headerCoordinations = stickyHeaderRef.current?.getBoundingClientRect();
            const footerCoordinations = stickyFooterRef.current?.getBoundingClientRect();
            const contentCoordinations = contentRef.current?.getBoundingClientRect();
            if ((itemType && !SCROLLING_ITEM_TYPES.includes(itemType)) ||
                !clientOffset ||
                !headerCoordinations ||
                !footerCoordinations ||
                !contentCoordinations ||
                !initialClientOffset ||
                !initialSourceClientOffset) {
                setScrollingDirection(ScrollingDirection.None);
                return;
            }
            const initialPointerOffsetY = initialClientOffset.y - initialSourceClientOffset.y;
            const normalizedClientOffsetY = clientOffset.y + initialPointerOffsetY;
            const shouldScrollUp = normalizedClientOffsetY <= headerCoordinations?.bottom + SCROLLING_ZONE_HEIGHT &&
                headerCoordinations?.bottom > contentCoordinations?.top;
            if (shouldScrollUp) {
                setScrollingDirection(ScrollingDirection.Up);
                return;
            }
            const shouldScrollDown = normalizedClientOffsetY > footerCoordinations?.bottom - SCROLLING_ZONE_HEIGHT &&
                contentCoordinations?.bottom > footerCoordinations?.bottom;
            if (shouldScrollDown) {
                setScrollingDirection(ScrollingDirection.Down);
                return;
            }
            setScrollingDirection(ScrollingDirection.None);
        });
        // we want to subscribe only once
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
    useInterval(() => {
        const scrollingTop = scrollingDirection * SCROLLING_STEP;
        findScrollable(contentRef.current)?.scrollBy({
            top: scrollingTop,
        });
    }, scrollingDirection === ScrollingDirection.None ? null : SCROLLING_INTERVAL);
}
/**
 * function goes from element to its parents and finds first scrollable element
 */
function findScrollable(element) {
    if (!element) {
        return document.documentElement;
    }
    if (element instanceof HTMLElement) {
        const overflowY = window.getComputedStyle(element).overflowY;
        const isScrollable = overflowY !== "visible" && overflowY !== "hidden";
        if (isScrollable && element.scrollHeight >= element.clientHeight) {
            return element;
        }
    }
    return findScrollable(element.parentNode);
}
