/**
 * Coroutine Plugin for ECSpresso
 *
 * ES6 generator-based coroutines for multi-step, frame-spanning scripted sequences.
 * A `coroutine` component holds a live generator. A system ticks all generators each
 * frame via `.next(dt)`. Helper generators (`waitSeconds`, `waitFrames`, `waitUntil`,
 * `waitForEvent`, `parallel`, `race`) compose via `yield*`.
 */
import { type BasePluginOptions } from 'ecspresso';
import type { EventsOfWorld, AnyECSpresso } from 'ecspresso';
/**
 * Yields void, returns void, receives deltaTime (number) via `.next(dt)`.
 * First `.next(dt)` initializes the generator (runs to first yield, dt discarded per JS spec).
 * Subsequent `.next(dt)` resume from yield with dt as the yield expression value.
 */
export type CoroutineGenerator = Generator<void, void, number>;
export interface CoroutineEventData {
    entityId: number;
}
export interface CoroutineState {
    generator: CoroutineGenerator;
    onComplete?: (data: CoroutineEventData) => void;
}
export interface CoroutineComponentTypes {
    coroutine: CoroutineState;
}
export interface CoroutinePluginOptions<G extends string = 'coroutines'> extends BasePluginOptions<G> {
}
export interface CoroutineOptions {
    onComplete?: (data: CoroutineEventData) => void;
}
/**
 * Create a coroutine component for spawning or adding to an entity.
 *
 * @param generator - The generator function to drive
 * @param options - Optional configuration (onComplete event)
 * @returns Component object suitable for spreading into spawn()
 */
export declare function createCoroutine(generator: CoroutineGenerator, options?: CoroutineOptions): Pick<CoroutineComponentTypes, 'coroutine'>;
/**
 * Wait for a specified number of seconds. Accumulates dt until elapsed >= seconds.
 * If seconds <= 0, returns immediately.
 */
export declare function waitSeconds(seconds: number): CoroutineGenerator;
/**
 * Wait for a specified number of frames. Yields `frames` times.
 * If frames <= 0, returns immediately.
 */
export declare function waitFrames(frames: number): CoroutineGenerator;
/**
 * Wait until a predicate returns true. Yields each frame until predicate is satisfied.
 * User closes over ecs if needed for state checks.
 */
export declare function waitUntil(predicate: () => boolean): CoroutineGenerator;
/**
 * Run multiple coroutines in parallel. Completes when all finish.
 * Initializes all sub-generators, ticks all each frame.
 * Empty array = immediate return.
 */
export declare function parallel(...coroutines: CoroutineGenerator[]): CoroutineGenerator;
/**
 * Run multiple coroutines, completing when the first one finishes.
 * Calls `.return()` on remaining generators (triggers finally blocks).
 * Empty array = immediate return.
 */
export declare function race(...coroutines: CoroutineGenerator[]): CoroutineGenerator;
/**
 * Wait until a matching event fires on the event bus.
 * Subscribes via eventBus.subscribe, yields until event received, unsubscribes in finally block.
 *
 * @param eventBus - Object with subscribe method (typically ecs.eventBus)
 * @param eventType - Event type name to listen for
 * @param filter - Optional predicate to filter events
 */
export declare function waitForEvent<ET extends Record<string, any>, E extends keyof ET & string>(eventBus: {
    subscribe(type: E, cb: (data: ET[E]) => void): () => void;
}, eventType: E, filter?: (data: ET[E]) => boolean): CoroutineGenerator;
/**
 * Structural interface for ECS methods used by cancelCoroutine.
 */
export interface CoroutineWorld {
    getComponent(entityId: number, componentName: string): unknown | undefined;
    commands: {
        removeComponent(entityId: number, componentName: string): void;
    };
}
/**
 * Cancel a running coroutine on an entity. Calls generator.return() (triggers finally blocks)
 * and queues component removal.
 *
 * @returns true if the entity had a coroutine that was cancelled, false otherwise
 */
export declare function cancelCoroutine(ecs: CoroutineWorld, entityId: number): boolean;
/**
 * Type-safe coroutine helpers that validate event names against a world's event types.
 * Use `createCoroutineHelpers<typeof ecs>()` to get compile-time validation.
 */
export interface CoroutineHelpers<W extends AnyECSpresso> {
    createCoroutine: (generator: CoroutineGenerator, options?: {
        onComplete?: (data: CoroutineEventData) => void;
    }) => Pick<CoroutineComponentTypes, 'coroutine'>;
    waitForEvent: <E extends keyof EventsOfWorld<W> & string>(eventBus: {
        subscribe(type: E, cb: (data: EventsOfWorld<W>[E]) => void): () => void;
    }, eventType: E, filter?: (data: EventsOfWorld<W>[E]) => boolean) => CoroutineGenerator;
}
/**
 * Create typed coroutine helpers that validate event names at compile time.
 *
 * @example
 * ```typescript
 * const { createCoroutine, waitForEvent } = createCoroutineHelpers<typeof ecs>();
 * ecs.spawn({ ...createCoroutine(myGen(), { onComplete: (data) => console.log(data.entityId) }) });
 * ```
 */
export declare function createCoroutineHelpers<W extends AnyECSpresso>(_world?: W): CoroutineHelpers<W>;
/**
 * Create a coroutine plugin for ECSpresso.
 *
 * This plugin provides:
 * - Coroutine system that ticks all generator-based coroutines each frame
 * - Automatic cleanup via dispose callback (triggers generator finally blocks)
 * - `onComplete` callback invocation
 * - Component removal on completion
 */
export declare function createCoroutinePlugin<G extends string = 'coroutines'>(options?: CoroutinePluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, CoroutineComponentTypes>, import("ecspresso").EmptyConfig, "coroutine-update", G, never, never>;
