import { Schema } from "@javelin/core";
import { ComponentStoreColumn } from "./archetype";
import { Component, ComponentOf } from "./component";
import { Entity } from "./entity";
import { Type } from "./type";
import { World } from "./world";
/**
 * A list of schemas that defines the signature of a query's results.
 * @example
 * const particle: Selector = [Position, Color]
 */
export declare type Selector = Schema[];
/**
 * An array of component instances that matches a selector.
 * @example
 * const results: SelectorResult<[Position, Color]> = [
 *   { x: 0, y: 0 },
 *   { value: 0xff0000 }
 * ]
 */
export declare type SelectorResult<$Selector extends Selector> = {
    [K in keyof $Selector]: $Selector[K] extends Schema ? ComponentOf<$Selector[K]> : Component;
};
/**
 * A "holey" `SelectorResult` where empty values are null.
 * @example
 * const results: SelectorResultSparse<[Position, Color]> = [
 *   null,
 *   { value: 0xff0000 }
 * ]
 */
export declare type SelectorResultSparse<$Selector extends Selector> = {
    [K in keyof $Selector]: ($Selector[K] extends Schema ? ComponentOf<$Selector[K]> : Component) | null;
};
/**
 * A subset of selector `$Selector`.
 * @example
 * const subset: SelectorSubset<[Position, Color]> = [Color]
 */
export declare type SelectorSubset<$Selector extends Selector> = ($Selector extends Array<infer _> ? _ : never)[];
/**
 * A record generated from an archetype with live references to the
 * archetype's entities and component data.
 */
export declare type QueryRecord<$Selector extends Selector> = [
    entities: ReadonlyArray<number>,
    columns: {
        [K in keyof $Selector]: $Selector[K] extends Schema ? ComponentStoreColumn<$Selector[K]> : never;
    },
    entityLookup: ReadonlyArray<number>
];
/**
 * A function used to iterate a query using the `query(fn)` syntax.
 * @example
 * const iteratee: QueryIteratee<[Position, Color]> = (entity, [position, color]) => {
 *   // ...
 * }
 */
export declare type QueryIteratee<$Selector extends Selector> = (entity: Entity, components: SelectorResult<$Selector>) => unknown;
/**
 * A live-updating, iterable collection of entity-components records that match
 * a provided selector (list of schemas).
 */
export declare type Query<$Selector extends Selector = Selector> = ((callback: QueryIteratee<$Selector>) => void) & {
    /**
     * The type signature of the query.
     */
    type: Type;
    /**
     * Query filters.
     */
    filters: QueryFilters;
    [Symbol.iterator](): IterableIterator<QueryRecord<$Selector>>;
    /**
     * Create a new query that excludes entities with components of provided
     * component type(s) from this query's results.
     */
    not(...selector: Selector): Query<$Selector>;
    /**
     * Create a new query that behaves the same as this query, but yields a
     * specified subset of components.
     */
    select<T extends SelectorSubset<$Selector>>(...include: T): Query<T>;
    /**
     * Get the results of a query for a specific entity.
     */
    get(entity: Entity, out?: SelectorResult<$Selector>): SelectorResult<$Selector>;
    /**
     * Check if an entity matches the query.
     */
    test(entity: Entity): boolean;
    /**
     * Bind the results of this query to a specific world.
     */
    bind(world: World): Query<$Selector>;
    /**
     * Check if this query matches a type signature.
     */
    matchesType(type: Type): boolean;
    /**
     * Check if this query equals another query.
     * @example
     * const a = createQuery(Enemy, EnemyAiState).not(Stun)
     * const b = createQuery(Enemy, EnemyAiState).not(Stun)
     * a.equals(b) // true
     * @example
     * const a = createQuery(Player)
     * const b = createQuery(Player).not(Burn)
     * a.equals(b) // false
     */
    equals(query: Query): boolean;
    /**
     * Create a new array from a list of components where components that do
     * not match the query are replaced with `null`.
     * @example
     * const moving = createQuery(Position, Velocity)
     * const components = [component(Position), component(Health), component(Velocity)]
     * moving.match(components) // [{}, null, {}]
     */
    match(components: Component[], out?: SelectorResultSparse<$Selector>): SelectorResultSparse<$Selector>;
};
declare type QueryFilters = {
    not: Set<number>;
};
/**
 * Create a query that can be used to iterate entities that match a selector.
 * Maintains a live-updating cache of entities, and can be used across multiple
 * worlds.
 * @example
 * const burning = createQuery(Player, Burn)
 * burning((entity, [player, burn]) => {
 *   player.health -= burn.damage
 * })
 * @example
 * for (const [entities, [p, b]] of burning) {
 *   for (let i = 0; i < entities.length; i++) {
 *     p[i].health -= b[i].damage
 *   }
 * }
 */
export declare function createQuery<$Selector extends Selector>(...select: $Selector): Query<$Selector>;
export {};
//# sourceMappingURL=query.d.ts.map