import { useEffect, useState } from 'react';

/**
 * Get index of first and last displayed item in current window scroll offset.
 * This is done to optimize performance for large lists.
 *
 * @param rowHeight height of single item in pixels
 * @param scrollOffset how many items above and below to render -- TODO: calculate from window height
 * @param dampening cause less re-renders -- only after jumping this x of elements, "staircase" effect
 * @returns [firstIndex, lastIndex]
 */
export const useVirtualizedRange = (
    rowHeight: number,
    scrollOffset = 40,
    dampening = 5,
    parentElement?: HTMLElement | null,
) => {
    const parent = parentElement ? parentElement : window;

    const [scrollIndex, setScrollIndex] = useState(
        Math.floor(
            (parent instanceof HTMLElement
                ? parent.scrollTop
                : parent.pageYOffset) / rowHeight,
        ),
    );

    useEffect(() => {
        const handleScroll = () => {
            requestAnimationFrame(() => {
                setScrollIndex(
                    Math.floor(
                        (parent instanceof HTMLElement
                            ? parent.scrollTop
                            : parent.pageYOffset) /
                            (rowHeight * dampening),
                    ) * dampening,
                );
            });
        };
        handleScroll();
        parent.addEventListener('scroll', handleScroll, { passive: true });

        return () => {
            parent.removeEventListener('scroll', handleScroll);
        };
    }, [rowHeight, dampening, parent]);

    return [scrollIndex - scrollOffset, scrollIndex + scrollOffset] as const;
};