import { DataFile } from '@comyata/fe/DataFile';
import { DataFileRegistry } from '@comyata/fe/DataFileRegistry';
import { Importers } from '@comyata/fe/Importers';
import { Parser } from '@comyata/run/Parser';
import { DataNode, IDataNode } from '@comyata/run/DataNode';
import { ComputeStats, runtime, IComputeStatsBase, NodeRuntimeBaggage, NodeRuntimeBaggageComplete, NodeComputeEngines, ComputeFn } from '@comyata/run/Runtime';
export interface Resolver {
    id: string;
    /**
     * @todo most pure-loaders shouldn't need to specify resolveRelative,
     *       but only with real-data, for filtering/sorting, (and not just a string as $load arg) something like 'genFileIdFromArgs" would make sense
     */
    scopes: string[];
    resolveDirectory?: (baseUrl: string) => ResolveContext;
    resolveFile: (fileUrl: string) => FileResolveContext;
}
export interface ResolveContext {
    /**
     * @todo maybe support a Symbol based id, to distinguish importers with same ID
     * @todo make import context required? would make the in-memory files complexer - or depending on their actual importer
     */
    importer?: string;
    resolveRelative?: ((relPath: string) => string);
}
export interface FileResolveContext extends ResolveContext {
    load: () => Promise<unknown> | unknown;
}
export interface FileComputeStats extends IComputeStatsBase {
    step: 'computeFile';
    file: string;
    stats: (FileComputeStats | ComputeStats)[];
    cached?: 0 | 1 | 2;
    usages?: Map<DataFile, Set<IDataNode>>;
}
export type ImportContext = ResolveContext | FileResolveContext;
export type RuntimeContext<TNode extends IDataNode = IDataNode> = {
    registry: DataFileRegistry<TNode>;
    /**
     * Either an object containing the computed result for an file in the current run,
     * or a subscriber function if currently already running computations, which resolves with the computed data.
     *
     * Used as a runtime cache, as each file will always be executed with the same "context" the resulted computations are expected to be stable within one run.
     * This guarantees that multiple `$import/$load` on the same URL will always have the same data inside a single run.
     */
    fileEvals: Map<DataFile, {
        result: unknown;
    } | ((requestingFilesChain: Set<DataFile>, requestingNodesChain: Set<IDataNode>) => Promise<unknown>)>;
    fileEvalsAwaiter: Map<DataFile, Set<DataFile>>;
    fileListener: Map<DataFile, ((result: unknown, err?: any) => void)[]>;
    /**
     * map which DataFile is used by which DataFile in which DataNode
     */
    usages: Map<DataFile, Map<DataFile, Set<IDataNode>>>;
};
export interface FileRuntimeBaggage<TNode extends IDataNode> extends NodeRuntimeBaggage<TNode> {
    dataFile: DataFile<TNode | IDataNode>;
    filesChain: Set<DataFile<TNode | IDataNode>>;
    computeStats: FileComputeStats;
    runtimeContext: RuntimeContext<TNode | IDataNode>;
    fileEngine: Pick<FileEngine<any>, 'run' | 'fetchFile'>;
}
export type FileComputeFn<TNode extends IDataNode, C = unknown, TBaggage extends FileRuntimeBaggage<TNode> = FileRuntimeBaggage<TNode>> = ComputeFn<TNode, C, TBaggage & NodeRuntimeBaggageComplete<TNode | IDataNode>>;
export type FileComputeFn2<TNode extends IDataNode, C = unknown> = (dataNode: TNode, context: C, parentData: unknown[], runtimeBaggage: FileRuntimeBaggage<TNode | IDataNode> & NodeRuntimeBaggageComplete<TNode | IDataNode>) => Promise<unknown>;
type FileComputeEngines<TNode extends IDataNode, C = unknown, TBaggage extends FileRuntimeBaggage<TNode> = FileRuntimeBaggage<TNode>> = NodeComputeEngines<TNode, C, TBaggage>;
declare class SubscribeMap<K, V> extends Map<K, V> {
    private readonly listeners;
    set(key: K, value: V): this;
    delete(key: K): boolean;
    clear(): void;
    onAdd(cb: (key: K, value: V) => void): () => void;
    onDelete(cb: (deletedKey: K) => void): () => void;
}
export declare class FileEngine<TNode extends typeof DataNode> {
    readonly parser: Parser<TNode>;
    readonly files: SubscribeMap<string, DataFile<InstanceType<TNode>>>;
    readonly compute: FileComputeEngines<InstanceType<TNode>>;
    readonly processorOptions: Parameters<typeof runtime>[3];
    private readonly importer;
    constructor({ nodes, compute, importer, processorOptions, parserOptions, }: {
        nodes: TNode[];
        compute: FileComputeEngines<InstanceType<TNode>>;
        importer?: Importers;
        processorOptions?: Parameters<typeof runtime>[3];
        parserOptions?: Partial<Parser<TNode>['options']>;
    });
    /**
     * @todo risky method, only use outside of computations/runs, to not accidentally access the wrong files cache,
     *       safe to use outside of runs
     */
    contextOf(contextBaseUrl: string): ResolveContext;
    /**
     * @todo maybe move into registry?
     * @todo risky method, only use outside of computations/runs, to not accidentally access the wrong files cache;
     *       safe to use outside of runs
     */
    fileRef(file: string, importContext?: ImportContext): DataFile<InstanceType<TNode>>;
    register(id: string, objOrEval: unknown, importContext?: ImportContext): DataFile<InstanceType<TNode>>;
    private newFile;
    fetchFile(dataFile: DataFile<InstanceType<TNode>>, registry: DataFileRegistry<InstanceType<TNode>>, statsList?: any[]): Promise<unknown>;
    run(dataFile: DataFile<InstanceType<TNode>>, context?: unknown, runtimeContext?: RuntimeContext<InstanceType<TNode>>, { filesChain, nodesChain, ...baggage }?: {
        filesChain?: Set<DataFile<InstanceType<TNode>>>;
        nodesChain?: Set<InstanceType<TNode>>;
        abort?: AbortSignal;
    }): Promise<[unknown, FileComputeStats, RuntimeContext<InstanceType<TNode>>]>;
}
export {};
