import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createRef, forwardRef, useLayoutEffect, useMemo, useRef, useState, } from "react";
import Styles from "./InfinityScroll.module.scss";
export function shouldIncrementPage(howMuchTheParentScrolled, prevSectionPosition, nextSectionPosition) {
    if (howMuchTheParentScrolled === nextSectionPosition)
        return 1;
    else if (howMuchTheParentScrolled === prevSectionPosition)
        return -1;
    else
        return 0;
}
export function keys(currPage) {
    return [currPage % 3, (currPage + 1) % 3, (currPage + 2) % 3]
        .map((a) => `step_${a}`)
        .reverse();
}
export function getItemsFactory(pageSize, items, isCountTheSameOrLowerThanPage) {
    return function getItems(page, offset, _pageSize = pageSize) {
        let from = page * _pageSize + offset;
        if (from < 0)
            from = items.length + from;
        if (from > items.length)
            from = from - items.length;
        const to = from + _pageSize;
        const slicedItems = items.slice(from, to);
        if (slicedItems.length < _pageSize && !isCountTheSameOrLowerThanPage) {
            slicedItems.push(...getItems(0, 0, _pageSize - slicedItems.length));
        }
        return slicedItems.map((i, index) => typeof i === "object"
            ? {
                ...i,
                key: index,
            }
            : i);
    };
}
function _InfinityScroll({ items, pageSize, initialPage = 0, pageClass, className = "", }, ref) {
    const [currPage, setCurrPage] = useState({
        page: initialPage,
        offset: 0,
    });
    const parentDiv = useMemo(() => {
        return ref || createRef();
    }, [ref]);
    const prevDiv = useRef(null);
    const currDiv = useRef(null);
    const nextDiv = useRef(null);
    const isCountTheSameOrLowerThanPage = items.length <= pageSize;
    const getItems = useMemo(() => getItemsFactory(pageSize, items, isCountTheSameOrLowerThanPage), [pageSize, items, isCountTheSameOrLowerThanPage]);
    useLayoutEffect(() => {
        if (isCountTheSameOrLowerThanPage || window.PRERENDER)
            return;
        const viewportWidth = parentDiv.current.clientWidth;
        const centerScroll = parentDiv.current.scrollWidth / 2;
        parentDiv.current.scrollTo({
            left: centerScroll - viewportWidth / 2,
        });
    }, [isCountTheSameOrLowerThanPage, currPage.page, currPage.offset, items]);
    const [beforeKey, currKey, afterKey] = keys(currPage.page);
    return (_jsxs("div", { ref: parentDiv, className: `${Styles.container} ${className}`, "data-testid": InfinityDataTestId.ROOT, onScroll: !isCountTheSameOrLowerThanPage
            ? () => {
                const pageToIncrement = shouldIncrementPage(Math.round(parentDiv.current.scrollLeft), prevDiv.current.offsetLeft, nextDiv.current.offsetLeft);
                if (pageToIncrement) {
                    setCurrPage((prev) => {
                        let nextPage = prev.page + pageToIncrement;
                        let offset = prev.offset;
                        if (nextPage < 0) {
                            nextPage = Math.round(items.length / pageSize) - 1;
                            const finalIndex = (nextPage + 1) * pageSize + offset;
                            const maxIndex = items.length;
                            const remainingItems = maxIndex + offset - finalIndex;
                            offset += remainingItems;
                            if (offset === -(items.length - 1))
                                offset = 1;
                        }
                        let nextIndex = nextPage * pageSize + offset;
                        if (nextIndex > items.length) {
                            offset = nextIndex - items.length;
                            nextPage = 0;
                        }
                        return {
                            page: nextPage,
                            offset,
                        };
                    });
                }
            }
            : undefined, children: [!isCountTheSameOrLowerThanPage && (_jsx("div", { className: pageClass, "data-testid": InfinityDataTestId.PREV_PAGE, ref: prevDiv, children: getItems(currPage.page - 1, currPage.offset) }, beforeKey)), _jsx("div", { className: pageClass, "data-testid": InfinityDataTestId.CURR_PAGE, ref: currDiv, children: getItems(currPage.page, currPage.offset) }, currKey), !isCountTheSameOrLowerThanPage && (_jsx("div", { className: pageClass, "data-testid": InfinityDataTestId.NEXT_PAGE, ref: nextDiv, children: getItems(currPage.page + 1, currPage.offset) }, afterKey))] }));
}
/**
 * A component that creates an infinite scrolling effect by showing different pages
 * of content as the user scrolls horizontally.
 **/
const InfinityScroll = forwardRef(_InfinityScroll);
export default InfinityScroll;
export var InfinityDataTestId;
(function (InfinityDataTestId) {
    InfinityDataTestId["PREV_PAGE"] = "infinity-prev";
    InfinityDataTestId["CURR_PAGE"] = "infinity-curr";
    InfinityDataTestId["NEXT_PAGE"] = "infinity-next";
    InfinityDataTestId["ROOT"] = "infinity-parent";
})(InfinityDataTestId || (InfinityDataTestId = {}));
//# sourceMappingURL=InfinityScroll.js.map