"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.For = void 0;
const state_1 = require("@legendapp/state");
const react_1 = require("react");
const reactive_observer_1 = require("./reactive-observer");
const useSelector_1 = require("./useSelector");
const autoMemoCache = new Map();
function For({ each, eachValues, optimized: isOptimized, item, itemProps, sortValues, children, }) {
    var _a;
    if (!each && !eachValues)
        return null;
    if (eachValues) {
        each = eachValues;
        if (process.env.NODE_ENV === 'development') {
            console.log('[legend-state]: "eachValues" prop is deprecated and will be removed in the next major version. Please use "each" prop instead.');
        }
    }
    const obs = each || eachValues;
    // Get the raw value with a shallow listener so this list only re-renders
    // when the array length changes
    const value = (0, useSelector_1.useSelector)(() => obs.get(isOptimized ? state_1.optimized : true));
    // The child function gets wrapped in a memoized observer component
    if (!item && children) {
        // Update the ref so the generated component uses the latest function
        const refChildren = (0, react_1.useRef)();
        refChildren.current = children;
        item = (0, react_1.useMemo)(() => (0, reactive_observer_1.observer)(({ item }) => refChildren.current(item)), []);
    }
    else {
        // @ts-expect-error $$typeof is private
        if (item.$$typeof !== Symbol.for('react.memo')) {
            let memod = autoMemoCache.get(item);
            if (!memod) {
                memod = (0, react_1.memo)(item);
                autoMemoCache.set(item, memod);
            }
            item = memod;
        }
    }
    // This early out needs to be after any hooks
    if (!value)
        return null;
    // Create the child elements
    const out = [];
    const isArr = (0, state_1.isArray)(value);
    if (isArr) {
        // Get the appropriate id field
        const v0 = value[0];
        const node = (0, state_1.getNode)(obs);
        const length = value.length;
        const idField = length > 0
            ? (node && (0, state_1.findIDKey)(v0, node)) ||
                (v0.id !== undefined ? 'id' : v0.key !== undefined ? 'key' : undefined)
            : undefined;
        const isIdFieldFunction = (0, state_1.isFunction)(idField);
        for (let i = 0; i < length; i++) {
            if (value[i]) {
                const val = value[i];
                const key = (_a = (isIdFieldFunction ? idField(val) : val[idField])) !== null && _a !== void 0 ? _a : i;
                const props = { key, id: key, item: each[i] };
                out.push((0, react_1.createElement)(item, itemProps ? Object.assign(props, itemProps) : props));
            }
        }
    }
    else {
        // Render the values of the object / Map
        const isMap = value instanceof Map;
        const keys = isMap ? Array.from(value.keys()) : Object.keys(value);
        if (sortValues) {
            keys.sort((A, B) => sortValues(isMap ? value.get(A) : value[A], isMap ? value.get(B) : value[B], A, B));
        }
        for (let i = 0; i < keys.length; i++) {
            const key = keys[i];
            if (isMap ? value.get(key) : value[key]) {
                const props = {
                    key,
                    id: key,
                    item: isMap ? each.get(key) : each[key],
                };
                out.push((0, react_1.createElement)(item, itemProps ? Object.assign(props, itemProps) : props));
            }
        }
    }
    return out;
}
exports.For = For;
//# sourceMappingURL=For.jsx.map