/** A high-level task that can be started and stepped through */
export interface Task<TReturn, TaskTag extends {
    id: string;
} = {
    id: string;
}, TError extends Error = Error> {
    readonly id: number;
    readonly timestamp: number;
    readonly builder: TaskBuilder<TReturn, TaskTag>;
    /** The parent task spawning this subtask, if any */
    readonly parent?: Task<unknown, TaskTag, TError>;
    /** A name to identify the task */
    readonly name?: string;
    /** A tag to identify the task programmatically */
    readonly tag?: TaskTag;
    /** The task's priority */
    readonly priority: TaskPriority;
    /** The concurrency group this task belongs to */
    readonly group?: TaskConcurrencyGroup;
    /** How the task should behave when interrupted */
    readonly interrupt: TaskInterruptBehavior;
    /** Starts the task it if hasn't been started yet, and executes the next step of the task */
    step(): Promise<TaskStepResult<TReturn, TaskTag>>;
    /** Stops the task without further executing it, cleans up, and prepares it for starting again */
    reset(): Promise<void>;
    /** Resolves the task's promise to notify the caller */
    resolve(result: TReturn): void;
    /** Rejects the task's promise to notify the caller */
    reject(error: TError): void;
    /** The current state of the task */
    get state(): TaskState;
    readonly generator: ReturnType<TaskBuilder<TReturn>["task"]> | undefined;
    readonly promise: Promise<TReturn>;
}
/** Defines the necessary information for creating a task */
export interface TaskBuilder<TReturn, TaskTag extends {
    id: string;
} = {
    id: string;
}, TInner = unknown> {
    /** A name to identify the task */
    name?: string;
    /** A tag to identify the task programmatically */
    tag?: TaskTag;
    /** The task's priority */
    priority: TaskPriority;
    /** How the task should behave when interrupted */
    interrupt?: TaskInterruptBehavior;
    /** The concurrency group this task belongs to */
    group?: TaskConcurrencyGroup;
    /**
     * The task's main generator function. This is called repeatedly until it's done.
     * The function must yield at points where it may be interrupted.
     *
     * At those points, the task can also wait for something to happen:
     * - Either a Promise, in which case it must yield a function that returns that Promise
     * - Or another task, in which case it must yield a TaskBuilder object or a function that returns one
     *
     * Yielded Promises should not spawn new tasks. If they do, the spawned tasks MUST have a higher priority than the parent task.
     */
    task: () => AsyncGenerator<(() => Promise<unknown> | TaskBuilder<unknown, TaskTag, unknown>) | (() => TaskBuilder<unknown, TaskTag, unknown>) | TaskBuilder<unknown, TaskTag, unknown> | undefined, TReturn, TInner>;
    /** A cleanup function that gets called when the task is dropped */
    cleanup?: () => Promise<void>;
}
export type TaskReturnType<T extends TaskBuilder<unknown>> = T extends TaskBuilder<infer R> ? R : never;
/**
 * The priority of a task.
 *
 * Higher priority tasks are executed first and interrupt lower priority tasks.
 * The recommended priority for application-initiated communication is `Normal`.
 * `Low` and `Lower` are recommended for internal long-running tasks that should not interfere with user-initiated tasks.
 * `Idle` is recommended for tasks that should only run when no other tasks are pending.
 */
export declare enum TaskPriority {
    Highest = 0,
    High = 1,
    Normal = 2,
    Low = 3,
    Lower = 4,
    Idle = 5
}
export declare enum TaskState {
    /** The task has not been created yet */
    None = 0,
    /** The task is being executed */
    Active = 1,
    /** The task is waiting for a Promise to resolve */
    AwaitingPromise = 2,
    /** The task is waiting for another task to finish */
    AwaitingTask = 3,
    /** The task is finished */
    Done = 4
}
export declare enum TaskInterruptBehavior {
    /** The task may not be interrupted */
    Forbidden = 0,
    /** The task will be resumed after being interrupted (default) */
    Resume = 1,
    /** The task needs to be restarted after being interrupted */
    Restart = 2
}
export type TaskStepResult<T, TaskTag extends {
    id: string;
} = {
    id: string;
}> = {
    newState: TaskState.Done;
    result: T;
} | {
    newState: TaskState.Active;
} | {
    newState: TaskState.AwaitingPromise;
    promise: Promise<unknown>;
} | {
    newState: TaskState.AwaitingTask;
    task: Task<unknown, TaskTag>;
};
/** Identifies a concurrency group. Tasks within the same group cannot run concurrently. */
export interface TaskConcurrencyGroup {
    id: string;
}
export declare class TaskScheduler<TaskTag extends {
    id: string;
} = {
    id: string;
}, TError extends Error = Error> {
    private defaultErrorFactory;
    private verbose;
    constructor(defaultErrorFactory?: () => TError, verbose?: boolean);
    private _tasks;
    private _currentTask;
    private _idGenerator;
    private _continueSignal;
    private _stopSignal;
    private _stopPromise;
    queueTask<T>(builder: TaskBuilder<T, TaskTag>): Promise<T>;
    /** Removes/stops tasks matching the given predicate. Returns `true` when a task was removed, `false` otherwise. */
    removeTasks(predicate: (task: Task<unknown, TaskTag>) => boolean, reason?: TError): Promise<boolean>;
    findTask<T = unknown>(predicate: (task: Task<T, TaskTag>) => boolean): Promise<T> | undefined;
    /** Creates a task that can be executed */
    private createTask;
    start(): void;
    private run;
    stop(): Promise<void>;
}
//# sourceMappingURL=Task.d.ts.map