"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useInfiniteQuery = void 0;
const react_1 = require("@based/react");
const react_2 = require("react");
const useCallbackRef_1 = require("./useCallbackRef");
function useInfiniteQuery(props) {
    const client = (0, react_1.useClient)();
    const subscriptions = (0, react_2.useRef)([]);
    const dataChecksums = (0, react_2.useRef)([]);
    const fetchingMore = (0, react_2.useRef)(false);
    const queryFn = (0, useCallbackRef_1.useCallbackRef)(props.queryFn);
    const accessFn = (0, useCallbackRef_1.useCallbackRef)(props.accessFn);
    const [visibleElements, setVisibleElements] = (0, react_2.useState)();
    const [didFilterChange, setDidFilterChange] = (0, react_2.useState)(false);
    const [data, setData] = (0, react_2.useState)([]);
    const chunkSize = (0, react_2.useMemo)(() => Math.max(...data.map((e) => (e ? accessFn(e) : []).length)), [data, accessFn]);
    const flatData = (0, react_2.useMemo)(() => data.flatMap((e) => (e ? accessFn(e) : [])), [data, accessFn]);
    const fetchMore = (0, react_2.useCallback)(() => {
        if (!fetchingMore.current) {
            fetchingMore.current = true;
            const index = subscriptions.current.length;
            subscriptions.current[index] = client
                .query('db', queryFn(flatData.length))
                .subscribe((chunk, checksum) => {
                dataChecksums.current[index] = checksum;
                // TODO: can be greatly optmized by not copying stuff
                // just use checksum
                // test with 100 items at least and updating every 1ms youll see
                // checksum based
                setData((prevData) => {
                    const newData = [...prevData];
                    newData[index] = chunk;
                    console.log('WHAT IS NEW DATA', newData);
                    return newData;
                });
                fetchingMore.current = false;
            });
        }
    }, [flatData.length]);
    (0, react_2.useEffect)(() => {
        fetchMore();
        return () => {
            for (const unsubscribe of subscriptions.current) {
                unsubscribe?.();
            }
        };
    }, []);
    const filterChange = () => {
        setDidFilterChange(true);
    };
    (0, react_2.useEffect)(() => {
        if (didFilterChange) {
            for (const unsubscribe of subscriptions.current) {
                unsubscribe?.();
            }
            setData([]);
            // console.log('reached here')
            fetchingMore.current = false;
            fetchMore();
        }
        setDidFilterChange(false);
    }, [didFilterChange]);
    (0, react_2.useEffect)(() => {
        if (visibleElements?.length) {
            const firstVisibleChunkIndex = Math.floor(Math.min(...visibleElements) / chunkSize);
            const lastVisibleChunkIndex = Math.ceil(Math.max(...visibleElements) / chunkSize);
            for (let i = 0; i < subscriptions.current.length; i++) {
                if (i < firstVisibleChunkIndex || i > lastVisibleChunkIndex) {
                    const unsubscribe = subscriptions.current[i];
                    if (unsubscribe) {
                        unsubscribe();
                        subscriptions.current[i] = null;
                    }
                }
                else {
                    if (subscriptions.current[i] === null) {
                        const unsubscribe = client
                            .query('db', queryFn(i * chunkSize))
                            .subscribe((chunk, checksum) => {
                            if (dataChecksums.current[i] !== checksum) {
                                dataChecksums.current[i] = checksum;
                                // yes
                                setData((prevData) => {
                                    const newData = [...prevData];
                                    newData[i] = chunk;
                                    return newData;
                                });
                            }
                        });
                        subscriptions.current[i] = unsubscribe;
                    }
                }
            }
        }
    }, [visibleElements, chunkSize]);
    return { data: flatData, fetchMore, setVisibleElements, filterChange };
}
exports.useInfiniteQuery = useInfiniteQuery;
//# sourceMappingURL=useInfiniteQuery.js.map