import * as React from 'react';
import { flushSync } from 'react-dom';
import { Virtualizer, elementScroll, observeElementOffset, observeElementRect, observeWindowOffset, observeWindowRect, windowScroll, } from '../virtual-core';
export * from '../virtual-core';
const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect;
function useVirtualizerBase(options) {
    const rerender = React.useReducer(() => ({}), {})[1];
    const resolvedOptions = {
        ...options,
        onChange: (instance, sync) => {
            var _a;
            if (sync) {
                flushSync(rerender);
            }
            else {
                rerender();
            }
            (_a = options.onChange) === null || _a === void 0 ? void 0 : _a.call(options, instance, sync);
        },
    };
    const [instance] = React.useState(() => new Virtualizer(resolvedOptions));
    instance.setOptions(resolvedOptions);
    useIsomorphicLayoutEffect(() => {
        return instance._didMount();
    }, []);
    useIsomorphicLayoutEffect(() => {
        return instance._willUpdate();
    });
    return instance;
}
export function useVirtualizer(options) {
    return useVirtualizerBase({
        observeElementRect,
        observeElementOffset,
        scrollToFn: elementScroll,
        ...options,
    });
}
export function useWindowVirtualizer(options) {
    return useVirtualizerBase({
        getScrollElement: () => (typeof document !== 'undefined' ? window : null),
        observeElementRect: observeWindowRect,
        observeElementOffset: observeWindowOffset,
        scrollToFn: windowScroll,
        initialOffset: () => (typeof document !== 'undefined' ? window.scrollY : 0),
        ...options,
    });
}
