import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useInsertionEffect, useMemo, useState, } from "react";
import { useRawAsynControl } from "../hooks/useAsyncControl";
class Subscriber {
    sharedCbs = {};
    latest = {};
    register(cbId, cb) {
        if (!this.sharedCbs[cbId])
            this.sharedCbs[cbId] = [];
        this.sharedCbs[cbId].push(cb);
        return (...args) => {
            this.latest[cbId] = args;
            for (let cb of this.sharedCbs[cbId])
                cb(...args);
        };
    }
    unregister(cbId, cb) {
        const cbIdx = this.sharedCbs[cbId].indexOf(cb);
        this.sharedCbs[cbId].splice(cbIdx, 1);
    }
    current(cbId) {
        return this.latest[cbId];
    }
}
/**
 * The context used to share state across components.
 */
export const ContextAsyncControlContext = createContext(null);
/**
 * Provider component to wrap the application context.
 */
export default function ContextAsyncControlProvider({ children, }) {
    return (_jsx(ContextAsyncControlContext.Provider, { value: {}, children: children }));
}
/**
 * Hook to share state between components.
 */
export function useShareState(controlId, stateId) {
    const ctx = useContext(ContextAsyncControlContext);
    const [state, setLocalState] = useState(() => {
        if (!ctx[controlId])
            ctx[controlId] = new Subscriber();
        const initAs = ctx[controlId].current(stateId)?.[0];
        return initAs;
    });
    const wrappedSetState = useMemo(() => {
        return ctx[controlId].register(stateId, setLocalState);
    }, []);
    useInsertionEffect(() => () => {
        ctx[controlId].unregister(stateId, setLocalState);
    }, []);
    return [state, wrappedSetState];
}
/**
 * Hook to control context with error and loading states.
 */
export function useContextControl(controlId, functionsToWrap) {
    const [error, setError] = useShareState(controlId, "error");
    const [loading, setLoading] = useShareState(controlId, "loading");
    return useRawAsynControl(functionsToWrap, [error, setError], [loading, setLoading]);
}
//# sourceMappingURL=ContextAsyncControl.js.map