import type ECSpresso from "./ecspresso";
import type { SystemDefaults } from "./plugin";
import type { FilteredEntity, QueryDefinition, System, SystemPhase } from "./types";
import type { WorldConfig, EmptyConfig } from "./type-utils";
export declare const PROCESS_EACH_QUERY: "__each";
type ProcessEachKey = typeof PROCESS_EACH_QUERY;
/**
 * Builder class for creating type-safe ECS Systems with proper query inference.
 * Systems are automatically registered with their ECSpresso instance when
 * finalized (at the start of initialize() or update()).
 */
export declare class SystemBuilder<Cfg extends WorldConfig = EmptyConfig, Queries extends Record<string, QueryDefinition<Cfg['components']>> = {}, Label extends string = string, SysGroups extends string = never, ResourceKeys extends keyof Cfg['resources'] = never, Singletons extends Record<string, QueryDefinition<Cfg['components']>> = {}> {
    private _label;
    private queries;
    private singletons;
    private processFunction?;
    private detachFunction?;
    private initializeFunction?;
    private eventHandlers?;
    private _priority;
    private _phase;
    private _groups;
    private _inScreens?;
    private _excludeScreens?;
    private _requiredAssets?;
    private _runWhenEmpty;
    private _entityEnterHandlers;
    private _resourceKeys?;
    constructor(_label: string, defaults?: SystemDefaults<Cfg>);
    get label(): string;
    /**
     * Create a system object with all configured properties.
     * @internal Used by ECSpresso to finalize and register the system
     */
    _createSystemObject(): System<Cfg, any, any>;
    /**
     * Set the priority of this system. Systems with higher priority values
     * execute before those with lower values. Systems with the same priority
     * execute in the order they were registered.
     * @param priority The priority value (default: 0)
     * @returns This SystemBuilder instance for method chaining
     */
    setPriority(priority: number): this;
    /**
     * Set the execution phase for this system.
     * Systems are grouped by phase and executed in order:
     * preUpdate -> fixedUpdate -> update -> postUpdate -> render
     * @param phase The phase to assign this system to (default: 'update')
     * @returns This SystemBuilder instance for method chaining
     */
    inPhase(phase: SystemPhase): this;
    /**
     * Add this system to a group. Systems can belong to multiple groups.
     * When any group a system belongs to is disabled, the system will be skipped.
     * @param groupName The name of the group to add the system to
     * @returns This SystemBuilder instance for method chaining
     */
    inGroup<G extends string>(groupName: G): SystemBuilder<Cfg, Queries, Label, SysGroups | G, ResourceKeys, Singletons>;
    /**
     * Restrict this system to only run in specified screens.
     * System will be skipped during update() when the current screen
     * is not in this list.
     * @param screens Array of screen names where this system should run
     * @returns This SystemBuilder instance for method chaining
     */
    inScreens(screens: ReadonlyArray<keyof Cfg['screens'] & string>): this;
    /**
     * Exclude this system from running in specified screens.
     * System will be skipped during update() when the current screen
     * is in this list.
     * @param screens Array of screen names where this system should NOT run
     * @returns This SystemBuilder instance for method chaining
     */
    excludeScreens(screens: ReadonlyArray<keyof Cfg['screens'] & string>): this;
    /**
     * Require specific assets to be loaded for this system to run.
     * System will be skipped during update() if any required asset
     * is not loaded.
     * @param assets Array of asset keys that must be loaded
     * @returns This SystemBuilder instance for method chaining
     */
    requiresAssets(assets: ReadonlyArray<keyof Cfg['assets'] & string>): this;
    /**
     * Allow this system to run even when all queries return zero entities.
     * By default, systems with queries are skipped when no entities match.
     */
    runWhenEmpty(): this;
    /**
     * Declare resource dependencies for this system. Resources are resolved
     * once (on first process call) and the same object is reused every frame.
     * The resolved resources are available as ctx.resources in setProcess.
     * @param keys Array of resource keys to resolve
     * @returns This SystemBuilder instance for method chaining
     */
    withResources<RK extends keyof Cfg['resources'] & string>(keys: readonly RK[]): SystemBuilder<Cfg, Queries, Label, SysGroups, RK, Singletons>;
    /**
     * Add a query definition to the system.
     *
     * When `mutates` is declared, every iterated entity is automatically
     * `markChanged`'d for each listed component after the system's
     * `process()` returns. Components in `with` but absent from `mutates`
     * are narrowed to `Readonly<T>` in the iteration entity type.
     */
    addQuery<QueryName extends string, WithComponents extends keyof Cfg['components'], WithoutComponents extends keyof Cfg['components'] = never, OptionalComponents extends keyof Cfg['components'] = never, MutatesComponents extends WithComponents = WithComponents, NewQueries extends Queries & Record<QueryName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents, MutatesComponents>> = Queries & Record<QueryName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents, MutatesComponents>>>(name: QueryName, definition: {
        with: ReadonlyArray<WithComponents>;
        without?: ReadonlyArray<WithoutComponents>;
        changed?: ReadonlyArray<WithComponents>;
        optional?: ReadonlyArray<OptionalComponents>;
        parentHas?: ReadonlyArray<keyof Cfg['components']>;
        mutates?: ReadonlyArray<MutatesComponents>;
    }): SystemBuilder<Cfg, NewQueries, Label, SysGroups, ResourceKeys, Singletons>;
    /**
     * Add a singleton query — a named query that yields a single
     * `FilteredEntity | undefined` instead of an array. Surfaces on the
     * process context's `queries` object alongside regular queries.
     *
     * When multiple entities match, the first is returned (no error). Use
     * the instance-level `getSingleton` / `tryGetSingleton` helpers on
     * `ECSpresso` if you need strictness guarantees.
     *
     * When `mutates` is declared, the resolved entity is automatically
     * `markChanged`'d for each listed component after the system's
     * `process()` returns. Components in `with` but absent from `mutates`
     * are narrowed to `Readonly<T>` in the iteration entity type.
     */
    addSingleton<SingletonName extends string, WithComponents extends keyof Cfg['components'], WithoutComponents extends keyof Cfg['components'] = never, OptionalComponents extends keyof Cfg['components'] = never, MutatesComponents extends WithComponents = WithComponents, NewSingletons extends Singletons & Record<SingletonName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents, MutatesComponents>> = Singletons & Record<SingletonName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents, MutatesComponents>>>(name: SingletonName, definition: {
        with: ReadonlyArray<WithComponents>;
        without?: ReadonlyArray<WithoutComponents>;
        changed?: ReadonlyArray<WithComponents>;
        optional?: ReadonlyArray<OptionalComponents>;
        parentHas?: ReadonlyArray<keyof Cfg['components']>;
        mutates?: ReadonlyArray<MutatesComponents>;
    }): SystemBuilder<Cfg, Queries, Label, SysGroups, ResourceKeys, NewSingletons>;
    /**
     * Set the system's process function that runs each update.
     * The callback receives a single context object { queries, dt, ecs, resources? }.
     * The context is pre-allocated per system and reused every frame.
     * @param process Function to process entities matching the system's queries each update
     * @returns This SystemBuilder instance for method chaining
     */
    setProcess(process: SystemProcessFn<Cfg, Queries, ResourceKeys, Singletons>): this;
    private _wrapWithResources;
    /**
     * Inline-query terminator: define a single query and a per-entity callback
     * in one call. Collapses the common `addQuery` + `setProcess` + for-loop
     * pattern into a single chain step.
     *
     * Only valid on a builder with no prior queries or process function —
     * TypeScript narrows `this` to `never` otherwise, and a runtime guard
     * throws for untyped callers. For multi-query systems use
     * `addQuery` + `setProcess`.
     *
     * When `mutates` is declared, the callback may `return false` to skip the
     * auto-mark for that specific entity. Returning `true`, `undefined`, or
     * any other value stamps all components listed in `mutates`. Components
     * in `with` but absent from `mutates` are narrowed to `Readonly<T>` on
     * the per-entity iteration type.
     *
     * @param definition Inline query definition (with / without / optional / changed / parentHas / mutates)
     * @param process Callback invoked once per matching entity each frame
     */
    setProcessEach<W extends keyof Cfg['components'], WO extends keyof Cfg['components'] = never, O extends keyof Cfg['components'] = never, M extends W = W>(this: [keyof Queries] extends [never] ? [keyof Singletons] extends [never] ? SystemBuilder<Cfg, Queries, Label, SysGroups, ResourceKeys, Singletons> : never : never, definition: {
        with: ReadonlyArray<W>;
        without?: ReadonlyArray<WO>;
        optional?: ReadonlyArray<O>;
        changed?: ReadonlyArray<W>;
        parentHas?: ReadonlyArray<keyof Cfg['components']>;
        mutates?: ReadonlyArray<M>;
    }, process: (ctx: {
        entity: FilteredEntity<Cfg['components'], W, WO, O, M>;
        dt: number;
        ecs: ECSpresso<Cfg>;
    } & ([ResourceKeys] extends [never] ? {} : {
        resources: {
            readonly [K in ResourceKeys]: Cfg['resources'][K];
        };
    })) => boolean | void): SystemBuilder<Cfg, Queries & Record<ProcessEachKey, QueryDefinition<Cfg['components'], W, WO, O, M>>, Label, SysGroups, ResourceKeys, Singletons>;
    /**
     * Register a callback that fires once per entity the first time it appears
     * in a query's results. Fires before process. Automatic cleanup when entity
     * leaves the query so re-entry fires the callback again.
     * @param queryName Name of a query previously added via addQuery
     * @param callback Function called with the entity and ecs instance
     * @returns This SystemBuilder instance for method chaining
     */
    setOnEntityEnter<QN extends keyof Queries & string>(queryName: QN, callback: (ctx: {
        entity: FilteredEntity<Cfg['components'], Queries[QN] extends QueryDefinition<Cfg['components'], infer W> ? W : never, Queries[QN] extends QueryDefinition<Cfg['components'], any, infer WO> ? WO : never, Queries[QN] extends QueryDefinition<Cfg['components'], any, any, infer O> ? O : never>;
        ecs: ECSpresso<Cfg>;
    }) => void): this;
    /**
     * Set the onDetach lifecycle hook
     * Called when the system is removed from the ECS
     * @param onDetach Function to run when this system is detached from the ECS
     * @returns This SystemBuilder instance for method chaining
     */
    setOnDetach(onDetach: SystemLifecycleFn<Cfg>): this;
    /**
     * Set the onInitialize lifecycle hook.
     *
     * Fires exactly once per system. For systems added before `initialize()`,
     * the hook is awaited inside `initialize()` itself. For systems added
     * after `initialize()` has returned, the hook fires on registration (at
     * the next `update()`'s finalize step) — async hooks run fire-and-forget,
     * so don't rely on completion ordering against the first `process` call.
     *
     * @param onInitialize Function to run when this system is initialized
     * @returns This SystemBuilder instance for method chaining
     */
    setOnInitialize(onInitialize: SystemLifecycleFn<Cfg>): this;
    /**
     * Set event handlers for the system
     * These handlers will be automatically subscribed when the system is attached
     * @param handlers Object mapping event names to handler functions
     * @returns This SystemBuilder instance for method chaining
     */
    setEventHandlers(handlers: {
        [EventName in keyof Cfg['events']]?: (ctx: {
            data: Cfg['events'][EventName];
            ecs: ECSpresso<Cfg>;
        }) => void;
    }): this;
}
type QueryResults<ComponentTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>, Singletons extends Record<string, QueryDefinition<ComponentTypes>> = {}> = {
    [QueryName in keyof Queries]: QueryName extends string ? FilteredEntity<ComponentTypes, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W> ? W : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, any, infer O> ? O : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W2, any, any, infer M> ? (unknown extends M ? W2 : M) : never>[] : never;
} & {
    [SingletonName in keyof Singletons]: SingletonName extends string ? FilteredEntity<ComponentTypes, Singletons[SingletonName] extends QueryDefinition<ComponentTypes, infer W> ? W : never, Singletons[SingletonName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never, Singletons[SingletonName] extends QueryDefinition<ComponentTypes, any, any, infer O> ? O : never, Singletons[SingletonName] extends QueryDefinition<ComponentTypes, infer W2, any, any, infer M> ? (unknown extends M ? W2 : M) : never> | undefined : never;
};
/**
 * Context object passed to system process functions.
 * Pre-allocated per system and reused every frame (zero per-frame allocation).
 * When resources are declared via withResources(), the context includes a
 * `resources` field with the resolved values (cached once on first call).
 */
export type ProcessContext<Cfg extends WorldConfig, Queries extends Record<string, QueryDefinition<Cfg['components']>>, ResourceKeys extends keyof Cfg['resources'] = never, Singletons extends Record<string, QueryDefinition<Cfg['components']>> = {}> = {
    queries: QueryResults<Cfg['components'], Queries, Singletons>;
    dt: number;
    ecs: ECSpresso<Cfg>;
} & ([ResourceKeys] extends [never] ? {} : {
    resources: {
        readonly [K in ResourceKeys]: Cfg['resources'][K];
    };
});
/**
 * Function signature for system process methods.
 * Receives a single context object with queries, dt, ecs, and optionally resources.
 */
export type SystemProcessFn<Cfg extends WorldConfig, Queries extends Record<string, QueryDefinition<Cfg['components']>>, ResourceKeys extends keyof Cfg['resources'] = never, Singletons extends Record<string, QueryDefinition<Cfg['components']>> = {}> = (ctx: ProcessContext<Cfg, Queries, ResourceKeys, Singletons>) => void;
/**
 * Type for system lifecycle functions
 * These can be asynchronous
 */
export type SystemLifecycleFn<Cfg extends WorldConfig> = (ecs: ECSpresso<Cfg>) => void | Promise<void>;
export {};
