import { getCheckpointManager } from './checkpoint-manager.js';
import { InfiniteLoopDetectionError } from './errors.js';
const MAX_ITERATIONS = 1000000;
export async function resumableMap(items, callback, mapId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(mapId);
    const startIndex = checkpoint?.currentIndex || 0;
    const results = checkpoint?.results || [];
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(mapId, i);
        }
        results[i] = await callback(items[i], i, items);
        const newCheckpoint = {
            loopId: mapId,
            currentIndex: i + 1,
            results: results,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(mapId);
    return results;
}
export async function resumableForEach(items, callback, forEachId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(forEachId);
    const startIndex = checkpoint?.currentIndex || 0;
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(forEachId, i);
        }
        await callback(items[i], i, items);
        const newCheckpoint = {
            loopId: forEachId,
            currentIndex: i + 1,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(forEachId);
}
export async function resumableFilter(items, callback, filterId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(filterId);
    const startIndex = checkpoint?.currentIndex || 0;
    const results = checkpoint?.results || [];
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(filterId, i);
        }
        const passed = await callback(items[i], i, items);
        if (passed) {
            results.push(items[i]);
        }
        const newCheckpoint = {
            loopId: filterId,
            currentIndex: i + 1,
            results: results,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(filterId);
    return results;
}
export async function resumableReduce(items, callback, initialValue, reduceId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(reduceId);
    const startIndex = checkpoint?.currentIndex || 0;
    let accumulator = checkpoint?.accumulator ?? initialValue;
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(reduceId, i);
        }
        accumulator = await callback(accumulator, items[i], i, items);
        const newCheckpoint = {
            loopId: reduceId,
            currentIndex: i + 1,
            accumulator: accumulator,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(reduceId);
    return accumulator;
}
export async function resumableFind(items, callback, findId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(findId);
    const startIndex = checkpoint?.currentIndex || 0;
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(findId, i);
        }
        const found = await callback(items[i], i, items);
        if (found) {
            await checkpointManager.clear(findId);
            return items[i];
        }
        const newCheckpoint = {
            loopId: findId,
            currentIndex: i + 1,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(findId);
    return undefined;
}
export async function resumableSome(items, callback, someId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(someId);
    const startIndex = checkpoint?.currentIndex || 0;
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(someId, i);
        }
        const result = await callback(items[i], i, items);
        if (result) {
            await checkpointManager.clear(someId);
            return true;
        }
        const newCheckpoint = {
            loopId: someId,
            currentIndex: i + 1,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(someId);
    return false;
}
export async function resumableEvery(items, callback, everyId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(everyId);
    const startIndex = checkpoint?.currentIndex || 0;
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(everyId, i);
        }
        const result = await callback(items[i], i, items);
        if (!result) {
            await checkpointManager.clear(everyId);
            return false;
        }
        const newCheckpoint = {
            loopId: everyId,
            currentIndex: i + 1,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(everyId);
    return true;
}
export async function resumableFlatMap(items, callback, flatMapId) {
    const checkpointManager = getCheckpointManager();
    const checkpoint = await checkpointManager.load(flatMapId);
    const startIndex = checkpoint?.currentIndex || 0;
    const results = checkpoint?.results || [];
    for (let i = startIndex; i < items.length; i++) {
        if (i > MAX_ITERATIONS) {
            throw new InfiniteLoopDetectionError(flatMapId, i);
        }
        const mapped = await callback(items[i], i, items);
        results.push(...mapped);
        const newCheckpoint = {
            loopId: flatMapId,
            currentIndex: i + 1,
            results: results,
            timestamp: Date.now(),
        };
        await checkpointManager.save(newCheckpoint);
    }
    await checkpointManager.clear(flatMapId);
    return results;
}
//# sourceMappingURL=resumable-arrays.js.map