import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable react-hooks/exhaustive-deps */
import * as React from 'react';
import { useRecoilCallback } from 'recoil';
import { cancelTask } from '../../api/core';
import {} from '../../api/http';
import { atomRegistry } from '../../shared/interactivity/store';
import {} from '../../types/core';
import { useRequestExtras } from './request-extras-context';
const GlobalTaskCtx = React.createContext(null);
export default function GlobalTaskProvider({ tasks, variableTaskMap, children }) {
    /**
     * Set holding all currently running tasks
     */
    const tasksRef = React.useRef(tasks !== null && tasks !== void 0 ? tasks : new Set());
    /**
     * Map of variableId -> Array(VariableTaskEntry)
     */
    const mapRef = React.useRef(variableTaskMap !== null && variableTaskMap !== void 0 ? variableTaskMap : new Map());
    const extras = useRequestExtras();
    const extrasRef = React.useRef(extras);
    extrasRef.current = extras;
    const refreshSelector = useRecoilCallback(({ set }) => (key) => {
        // refresh the selector by incrementing the associated trigger so next run will skip the cache
        set(atomRegistry.get(key), (prev) => (Object.assign(Object.assign({}, prev), { inc: prev.inc + 1 })));
    });
    const cleanupRunningTasks = React.useCallback((...variableIds) => {
        for (const variableId of variableIds) {
            const taskEntries = mapRef.current.get(variableId);
            // check if any of the currently running tasks are associated with the variable
            for (const runningTask of tasksRef.current) {
                const taskToCancel = taskEntries === null || taskEntries === void 0 ? void 0 : taskEntries.find((t) => t.taskId === runningTask);
                // found a match
                if (taskToCancel) {
                    // cancel the task and mark it as stopped
                    cancelTask(runningTask, extrasRef.current);
                    tasksRef.current.delete(runningTask);
                    if (taskToCancel.triggerKey) {
                        // make sure next time the selector runs it will run from scratch rather than using the cached value
                        refreshSelector(taskToCancel.triggerKey);
                    }
                }
            }
        }
    }, []);
    const startTask = React.useCallback((taskId, variableId, triggerKey) => {
        var _a;
        if (variableId) {
            // add the task to the variable -> tasks map
            const variableTaskEntries = (_a = mapRef.current.get(variableId)) !== null && _a !== void 0 ? _a : [];
            variableTaskEntries.push({ taskId, triggerKey });
            mapRef.current.set(variableId, variableTaskEntries);
        }
        tasksRef.current.add(taskId);
    }, []);
    const endTask = React.useCallback((taskId) => {
        tasksRef.current.delete(taskId);
    }, []);
    const getVariableTasks = React.useCallback((...variableIds) => {
        let taskIds = [];
        for (const variable of variableIds) {
            const associatedTasks = mapRef.current.get(variable);
            // If there are associated tasks in the map
            if (associatedTasks) {
                // check which ones are currently running
                taskIds = associatedTasks
                    .filter((entry) => tasksRef.current.has(entry.taskId))
                    .map((entry) => entry.taskId);
            }
        }
        return taskIds;
    }, []);
    const hasRunningTasks = React.useCallback(() => {
        return tasksRef.current.size > 0;
    }, []);
    const value = React.useMemo(() => ({
        cleanupRunningTasks,
        endTask,
        getVariableTasks,
        hasRunningTasks,
        startTask,
    }), [cleanupRunningTasks, endTask, getVariableTasks, hasRunningTasks, startTask]);
    return _jsx(GlobalTaskCtx.Provider, { value: value, children: children });
}
export function useTaskContext() {
    const taskCtx = React.useContext(GlobalTaskCtx);
    if (!taskCtx) {
        throw new Error('useTaskContext must be used within GlobalTaskProvider');
    }
    return taskCtx;
}
//# sourceMappingURL=global-task-context.js.map