import { jsx as _jsx } from "react/jsx-runtime";
import copy from 'lodash/cloneDeep';
import isEqual from 'lodash/isEqual';
import * as React from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import { VariableSizeList } from 'react-window';
import { DynamicComponent, useVariable } from '../../shared';
import { FallbackCtx } from '../../shared/context';
import { useFallbackCtx } from '../../shared/context/fallback-context';
import { resolveNested } from '../../shared/interactivity/nested';
import {} from '../../types/core';
import { applyMarkers, getInjectionMarkers } from './templating';
const createItemData = (items, renderer, markers, getItemKey) => ({
    items,
    renderer,
    markers,
    getItemKey,
});
/**
 * Memoized child that applies the precomputed loop variable paths to the renderer,
 * for the given loop item.
 */
const ForChild = React.memo((props) => {
    const transformedRenderer = React.useMemo(() => {
        let component;
        try {
            component = applyMarkers({
                renderer: props.data.renderer,
                markers: props.data.markers,
                loopValue: props.data.items[props.index],
                itemKey: props.data.getItemKey(props.index, props.data),
                index: props.index,
                itemsLength: props.data.items.length,
            });
        }
        catch (e) {
            // eslint-disable-next-line no-console
            console.error('Failed to apply markers', e);
            component = copy(props.data.renderer);
        }
        // IMPORTANT: apply style passed through from e.g. the VariableSizeList, which positions it correctly
        component.props.style = Object.assign(Object.assign({}, component.props.style), props.style);
        return component;
    }, [props.data, props.index, props.style]);
    return _jsx(DynamicComponent, { component: transformedRenderer });
}, isEqual);
function ForImpl(props) {
    const [items] = useVariable(props.items, { suspend: false });
    const markers = React.useMemo(() => getInjectionMarkers(props.renderer), [props.renderer]);
    const key = React.useMemo(() => { var _a, _b; return (_b = (_a = props.key_accessor) === null || _a === void 0 ? void 0 : _a.split('.')) !== null && _b !== void 0 ? _b : null; }, [props.key_accessor]);
    const getItemKey = React.useCallback((index, data) => (key ? resolveNested(data.items[index], key) : index), [key]);
    const itemData = React.useMemo(() => createItemData(items, props.renderer, markers, getItemKey), [items, props.renderer, markers, getItemKey]);
    const getItemSize = React.useCallback((index) => {
        // assuming virtualization is not null here
        if (typeof props.virtualization.size === 'string') {
            return items[index][props.virtualization.size];
        }
        return props.virtualization.size;
    }, [props.virtualization, items]);
    if (items.length === 0) {
        if (!props.placeholder) {
            return null;
        }
        return _jsx(DynamicComponent, { component: props.placeholder });
    }
    if (props.virtualization === null) {
        // reapply the parent suspend setting
        return (_jsx(FallbackCtx.Provider, { value: { suspend: props.suspend }, children: items.map((_, index) => (_jsx(ForChild, { data: itemData, index: index, style: {} }, getItemKey(index, itemData)))) }));
    }
    return (_jsx(FallbackCtx.Provider, { value: { suspend: props.suspend }, children: _jsx(AutoSizer, { children: ({ width, height }) => (_jsx(VariableSizeList, { height: height, width: width, itemCount: items.length, itemData: itemData, itemKey: getItemKey, itemSize: getItemSize, layout: props.virtualization.direction, children: ForChild })) }) }));
}
function For(props) {
    const { suspend } = useFallbackCtx();
    // Force disable suspend, as that defeats the purpose of this component.
    return (_jsx(FallbackCtx.Provider, { value: { suspend: false }, children: _jsx(ForImpl, Object.assign({}, props, { suspend: suspend })) }));
}
export default For;
//# sourceMappingURL=for.js.map