import { createEffect, createSignal, onCleanup } from "solid-js";
/**
 * Virtualizes a list of items, only rendering those visible in the scroll viewport.
 * Supports fixed and variable row heights, horizontal/vertical, and overscan.
 */
export function createVirtualizer(options) {
    const overscan = options.overscan ?? 5;
    const horizontal = options.horizontal ?? false;
    const getKey = options.getItemKey ?? ((i) => i);
    const [scrollOffset, setScrollOffset] = createSignal(0);
    const [containerSize, setContainerSize] = createSignal(0);
    const measurements = new Map();
    function getSize(index) {
        return measurements.get(index) ?? options.estimateSize(index);
    }
    function getItemOffset(index) {
        let offset = 0;
        for (let i = 0; i < index; i++) {
            offset += getSize(i);
        }
        return offset;
    }
    const totalSize = () => {
        const count = options.count();
        let total = 0;
        for (let i = 0; i < count; i++) {
            total += getSize(i);
        }
        return total;
    };
    const virtualItems = () => {
        const count = options.count();
        if (count === 0)
            return [];
        const offset = scrollOffset();
        const size = containerSize();
        if (size === 0)
            return [];
        let startIndex = 0;
        let accumulated = 0;
        while (startIndex < count && accumulated + getSize(startIndex) <= offset) {
            accumulated += getSize(startIndex);
            startIndex++;
        }
        let endIndex = startIndex;
        let visibleAccumulated = 0;
        while (endIndex < count && visibleAccumulated < size) {
            visibleAccumulated += getSize(endIndex);
            endIndex++;
        }
        const overscanStart = Math.max(0, startIndex - overscan);
        const overscanEnd = Math.min(count - 1, endIndex + overscan);
        const items = [];
        for (let i = overscanStart; i <= overscanEnd; i++) {
            const itemSize = getSize(i);
            const start = getItemOffset(i);
            items.push({
                index: i,
                start,
                end: start + itemSize,
                size: itemSize,
                key: getKey(i),
            });
        }
        return items;
    };
    createEffect(() => {
        const el = options.getScrollElement();
        if (!el)
            return;
        const sizeKey = horizontal ? "clientWidth" : "clientHeight";
        const scrollKey = horizontal ? "scrollLeft" : "scrollTop";
        setContainerSize(el[sizeKey]);
        setScrollOffset(el[scrollKey]);
        const onScroll = () => {
            setScrollOffset(el[scrollKey]);
        };
        const resizeObserver = new ResizeObserver(() => {
            setContainerSize(el[sizeKey]);
        });
        el.addEventListener("scroll", onScroll, { passive: true });
        resizeObserver.observe(el);
        onCleanup(() => {
            el.removeEventListener("scroll", onScroll);
            resizeObserver.disconnect();
        });
    });
    function scrollToIndex(index, opts) {
        const el = options.getScrollElement();
        if (!el)
            return;
        const itemOffset = getItemOffset(index);
        const itemSize = getSize(index);
        const viewSize = containerSize();
        const scrollKey = horizontal ? "scrollLeft" : "scrollTop";
        let target = itemOffset;
        if (opts?.align === "center") {
            target = itemOffset - viewSize / 2 + itemSize / 2;
        }
        else if (opts?.align === "end") {
            target = itemOffset - viewSize + itemSize;
        }
        el[scrollKey] = Math.max(0, target);
    }
    function measureElement(element) {
        if (!element)
            return;
        const index = Number(element.dataset.index);
        if (Number.isNaN(index))
            return;
        const size = horizontal ? element.offsetWidth : element.offsetHeight;
        measurements.set(index, size);
    }
    return { virtualItems, totalSize, scrollToIndex, scrollOffset, measureElement };
}
//# sourceMappingURL=create-virtualizer.js.map