import React, { useEffect, useRef, useCallback } from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { Flex, InfiniteLoader } from "../../../components";
const DefaultLoadingComponent = () => (React.createElement(Flex, { justifyContent: "center", alignItems: "center", height: "76px" },
    React.createElement(InfiniteLoader, null)));
function easeInOutCubic(t) {
    return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
export const VirtualList = ({ gap, hasNextPage = false, isLoading, itemHeight, items, LoadingComponent, onVisibleItemsScrollEnd, overscan = 5, renderItem, scrollToTop = false, bottomComponent, threshold = 5, }) => {
    const parentRef = useRef(null);
    const scrollToFn = useCallback((offset, options, instance) => {
        const element = instance.scrollElement;
        if (!element)
            return;
        const duration = options.behavior === "smooth" ? 100 : 0;
        if (duration === 0) {
            element.scrollTop = offset;
            return;
        }
        const startTime = performance.now();
        const startTop = element.scrollTop;
        const distanceToScroll = offset - startTop;
        const scrollStep = (currentTime) => {
            const elapsed = currentTime - startTime;
            const progress = Math.min(elapsed / duration, 1);
            const easedProgress = easeInOutCubic(progress);
            element.scrollTop = startTop + distanceToScroll * easedProgress;
            if (progress < 1) {
                requestAnimationFrame(scrollStep);
            }
        };
        requestAnimationFrame(scrollStep);
    }, []);
    const rowVirtualizer = useVirtualizer({
        gap,
        count: hasNextPage ? items.length + 1 : items.length,
        overscan,
        getScrollElement: () => parentRef.current,
        estimateSize: () => itemHeight,
        scrollToFn,
    });
    useEffect(() => {
        if (scrollToTop && parentRef.current) {
            scrollToFn(0, { behavior: "smooth" }, { scrollElement: parentRef.current });
        }
    }, [scrollToTop, scrollToFn]);
    const virtualItems = rowVirtualizer.getVirtualItems();
    useEffect(() => {
        if (!virtualItems.length)
            return;
        const lastItem = virtualItems[virtualItems.length - 1];
        if (lastItem.index >= items.length - 1 - threshold &&
            hasNextPage &&
            !isLoading &&
            onVisibleItemsScrollEnd) {
            onVisibleItemsScrollEnd();
        }
    }, [hasNextPage, onVisibleItemsScrollEnd, items.length, isLoading, threshold, virtualItems]);
    const showCustomLoadingComponent = !!LoadingComponent;
    const Loading = useCallback(() => (showCustomLoadingComponent ? LoadingComponent : React.createElement(DefaultLoadingComponent, null)), [showCustomLoadingComponent, LoadingComponent]);
    return (React.createElement("div", { ref: parentRef, style: { width: "100%", height: "100%", overflow: "auto", scrollbarWidth: "none" } },
        React.createElement("div", { style: {
                height: `${rowVirtualizer.getTotalSize()}px`,
                width: "100%",
                display: "flex",
                flexDirection: "column",
                position: "relative",
            } },
            rowVirtualizer.getVirtualItems().map((virtualRow) => {
                const item = items[virtualRow.index];
                return (React.createElement("div", { key: virtualRow.index, "data-index": virtualRow.index, ref: rowVirtualizer.measureElement, style: {
                        position: "absolute",
                        top: 0,
                        left: 0,
                        transform: `translateY(${virtualRow.start}px)`,
                        height: `${itemHeight}px`,
                        width: "100%",
                    } }, item ? renderItem(item) : React.createElement(Loading, null)));
            }),
            bottomComponent && (React.createElement("div", { style: {
                    position: "absolute",
                    top: `${rowVirtualizer.getTotalSize()}px`,
                    left: 0,
                    width: "100%",
                } }, bottomComponent))),
        isLoading && React.createElement(Loading, null)));
};
//# sourceMappingURL=VirtualList.js.map