import { jsx as _jsx } from "react/jsx-runtime";
/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { useRef, forwardRef, useImperativeHandle, useCallback, useMemo, useEffect, } from 'react';
import { VirtualizedList } from './VirtualizedList.js';
import { useScrollable } from '../../contexts/ScrollProvider.js';
import { Box } from 'ink';
import { useKeypress } from '../../hooks/useKeypress.js';
import { keyMatchers, Command } from '../../keyMatchers.js';
import { useAnimatedScrollbar } from '../../hooks/useAnimatedScrollbar.js';
const ANIMATION_FRAME_DURATION_MS = 33;
/**
 * @plan PLAN-20251215-OLDUI-SCROLL.P05
 * @requirement REQ-456.4
 */
function ScrollableList(props, ref) {
    const { hasFocus } = props;
    const virtualizedListRef = useRef(null);
    const containerRef = useRef(null);
    const smoothScrollState = useRef({
        intervalId: null,
        targetScrollTop: 0,
    });
    useImperativeHandle(ref, () => ({
        scrollBy: (delta) => virtualizedListRef.current?.scrollBy(delta),
        scrollTo: (offset) => virtualizedListRef.current?.scrollTo(offset),
        scrollToEnd: () => virtualizedListRef.current?.scrollToEnd(),
        scrollToIndex: (params) => virtualizedListRef.current?.scrollToIndex(params),
        scrollToItem: (params) => virtualizedListRef.current?.scrollToItem(params),
        getScrollIndex: () => virtualizedListRef.current?.getScrollIndex() ?? 0,
        getScrollState: () => virtualizedListRef.current?.getScrollState() ?? {
            scrollTop: 0,
            scrollHeight: 0,
            innerHeight: 0,
        },
    }), []);
    const getScrollState = useCallback(() => virtualizedListRef.current?.getScrollState() ?? {
        scrollTop: 0,
        scrollHeight: 0,
        innerHeight: 0,
    }, []);
    const scrollBy = useCallback((delta) => {
        virtualizedListRef.current?.scrollBy(delta);
    }, []);
    const stopSmoothScroll = useCallback(() => {
        if (smoothScrollState.current.intervalId !== null) {
            clearInterval(smoothScrollState.current.intervalId);
            smoothScrollState.current.intervalId = null;
        }
    }, []);
    const smoothScrollTo = useCallback((targetScrollTop) => {
        stopSmoothScroll();
        const scrollState = getScrollState();
        const startScrollTop = scrollState.scrollTop;
        const distance = targetScrollTop - startScrollTop;
        if (distance === 0) {
            return;
        }
        const duration = 200;
        const startTime = Date.now();
        const animate = () => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / duration, 1);
            // Ease-in-out
            const easeProgress = progress < 0.5
                ? 2 * progress * progress
                : -1 + (4 - 2 * progress) * progress;
            const newScrollTop = startScrollTop + distance * easeProgress;
            virtualizedListRef.current?.scrollTo(newScrollTop);
            if (progress < 1) {
                smoothScrollState.current.intervalId = setTimeout(animate, ANIMATION_FRAME_DURATION_MS);
            }
            else {
                smoothScrollState.current.intervalId = null;
            }
        };
        animate();
        smoothScrollState.current.targetScrollTop = targetScrollTop;
    }, [getScrollState, stopSmoothScroll]);
    useEffect(() => () => stopSmoothScroll(), [stopSmoothScroll]);
    const { scrollbarColor, flashScrollbar, scrollByWithAnimation } = useAnimatedScrollbar(hasFocus, scrollBy);
    useKeypress((key) => {
        if (keyMatchers[Command.SCROLL_UP](key)) {
            stopSmoothScroll();
            scrollByWithAnimation(-1);
        }
        else if (keyMatchers[Command.SCROLL_DOWN](key)) {
            stopSmoothScroll();
            scrollByWithAnimation(1);
        }
        else if (keyMatchers[Command.PAGE_UP](key) ||
            keyMatchers[Command.PAGE_DOWN](key)) {
            const direction = keyMatchers[Command.PAGE_UP](key) ? -1 : 1;
            const scrollState = getScrollState();
            const current = smoothScrollState.current.intervalId !== null
                ? smoothScrollState.current.targetScrollTop
                : scrollState.scrollTop;
            const innerHeight = scrollState.innerHeight;
            smoothScrollTo(current + direction * innerHeight);
            flashScrollbar();
        }
        else if (keyMatchers[Command.SCROLL_HOME](key)) {
            smoothScrollTo(0);
            flashScrollbar();
        }
        else if (keyMatchers[Command.SCROLL_END](key)) {
            // Resolve SCROLL_TO_ITEM_END to actual max scrollTop for animation
            const scrollState = getScrollState();
            const maxScrollTop = Math.max(scrollState.scrollHeight - scrollState.innerHeight, 0);
            smoothScrollTo(maxScrollTop);
            flashScrollbar();
        }
    }, { isActive: hasFocus });
    const hasFocusCallback = useCallback(() => hasFocus, [hasFocus]);
    const scrollableEntry = useMemo(() => ({
        ref: containerRef,
        getScrollState,
        scrollBy,
        scrollTo: (scrollTop) => virtualizedListRef.current?.scrollTo(scrollTop),
        hasFocus: hasFocusCallback,
        flashScrollbar,
    }), [getScrollState, hasFocusCallback, flashScrollbar, scrollBy]);
    useScrollable(scrollableEntry, hasFocus);
    return (_jsx(Box, { ref: containerRef, flexGrow: 1, flexShrink: 1, flexDirection: "column", overflow: "hidden", children: _jsx(VirtualizedList, { ref: virtualizedListRef, ...props, scrollbarThumbColor: scrollbarColor }) }));
}
const ScrollableListWithForwardRef = forwardRef(ScrollableList);
export { ScrollableListWithForwardRef as ScrollableList };
//# sourceMappingURL=ScrollableList.js.map