import { Component, ComponentCtor } from './Component';
import { Observable, Message } from '../Util/Observable';
import { OnInitialize, OnPreUpdate, OnPostUpdate, OnAdd, OnRemove } from '../Interfaces/LifecycleEvents';
import { Engine } from '../Engine';
import { InitializeEvent, PreUpdateEvent, PostUpdateEvent, AddEvent, RemoveEvent } from '../Events';
import { KillEvent } from '../Events';
import { EventEmitter, EventKey, Handler, Subscription } from '../EventEmitter';
import { Scene } from '../Scene';
import { MaybeKnownComponent } from './Types';
/**
 * Interface holding an entity component pair
 */
export interface EntityComponent {
    component: Component;
    entity: Entity;
}
/**
 * AddedComponent message
 */
export declare class AddedComponent implements Message<EntityComponent> {
    data: EntityComponent;
    readonly type: 'Component Added';
    constructor(data: EntityComponent);
}
/**
 * Type guard to know if message is f an Added Component
 */
export declare function isAddedComponent(x: Message<EntityComponent>): x is AddedComponent;
/**
 * RemovedComponent message
 */
export declare class RemovedComponent implements Message<EntityComponent> {
    data: EntityComponent;
    readonly type: 'Component Removed';
    constructor(data: EntityComponent);
}
/**
 * Type guard to know if message is for a Removed Component
 */
export declare function isRemovedComponent(x: Message<EntityComponent>): x is RemovedComponent;
/**
 * Built in events supported by all entities
 */
export type EntityEvents = {
    initialize: InitializeEvent;
    add: AddEvent;
    remove: RemoveEvent;
    preupdate: PreUpdateEvent;
    postupdate: PostUpdateEvent;
    kill: KillEvent;
};
export declare const EntityEvents: {
    readonly Add: "add";
    readonly Remove: "remove";
    readonly Initialize: "initialize";
    readonly PreUpdate: "preupdate";
    readonly PostUpdate: "postupdate";
    readonly Kill: "kill";
};
export interface EntityOptions<TComponents extends Component> {
    name?: string;
    components?: TComponents[];
    silenceWarnings?: boolean;
}
/**
 * An Entity is the base type of anything that can have behavior in Excalibur, they are part of the built in entity component system
 *
 * Entities can be strongly typed with the components they contain
 *
 * ```typescript
 * const entity = new Entity<ComponentA | ComponentB>();
 * entity.components.a; // Type ComponentA
 * entity.components.b; // Type ComponentB
 * ```
 */
export declare class Entity<TKnownComponents extends Component = any> implements OnInitialize, OnPreUpdate, OnPostUpdate, OnAdd, OnRemove {
    private static _ID;
    /**
     * The unique identifier for the entity
     */
    id: number;
    name: string;
    /**
     * Listen to or emit events for an entity
     */
    events: EventEmitter<EntityEvents>;
    private _tags;
    componentAdded$: Observable<Component>;
    componentRemoved$: Observable<Component>;
    tagAdded$: Observable<string>;
    tagRemoved$: Observable<string>;
    /**
     * Current components on the entity
     *
     * **Do not modify**
     *
     * Use addComponent/removeComponent otherwise the ECS will not be notified of changes.
     */
    readonly components: Map<Function, Component>;
    componentValues: Component[];
    private _componentsToRemove;
    constructor(options: EntityOptions<TKnownComponents>);
    constructor(components?: TKnownComponents[], name?: string);
    /**
     * The current scene that the entity is in, if any
     */
    scene: Scene | null;
    /**
     * Whether this entity is active, if set to false it will be reclaimed
     * @deprecated use isActive
     */
    get active(): boolean;
    /**
     * Whether this entity is active, if set to false it will be reclaimed
     * @deprecated use isActive
     */
    set active(val: boolean);
    /**
     * Whether this entity is active, if set to false it will be reclaimed
     */
    isActive: boolean;
    /**
     * Kill the entity, means it will no longer be updated. Kills are deferred to the end of the update.
     * If parented it will be removed from the parent when killed.
     */
    kill(): void;
    isKilled(): boolean;
    /**
     * Specifically get the tags on the entity from {@apilink TagsComponent}
     */
    get tags(): Set<string>;
    /**
     * Check if a tag exists on the entity
     * @param tag name to check for
     */
    hasTag(tag: string): boolean;
    /**
     * Adds a tag to an entity
     * @param tag
     */
    addTag(tag: string): Entity<TKnownComponents>;
    /**
     * Removes a tag on the entity
     *
     * Removals are deferred until the end of update
     * @param tag
     */
    removeTag(tag: string): Entity<TKnownComponents>;
    /**
     * The types of the components on the Entity
     */
    get types(): ComponentCtor[];
    /**
     * Returns all component instances on entity
     */
    getComponents(): Component[];
    /**
     * Verifies that an entity has all the required types
     * @param requiredTypes
     */
    hasAll<TComponent extends Component>(requiredTypes: ComponentCtor<TComponent>[]): boolean;
    /**
     * Verifies that an entity has all the required tags
     * @param requiredTags
     */
    hasAllTags(requiredTags: string[]): boolean;
    get<TComponent extends Component>(type: ComponentCtor<TComponent>): MaybeKnownComponent<TComponent, TKnownComponents>;
    private _parent;
    get parent(): Entity | null;
    childrenAdded$: Observable<Entity<any>>;
    childrenRemoved$: Observable<Entity<any>>;
    private _children;
    /**
     * Get the direct children of this entity
     */
    get children(): readonly Entity[];
    /**
     * Unparents this entity, if there is a parent. Otherwise it does nothing.
     */
    unparent(): void;
    /**
     * Adds an entity to be a child of this entity
     * @param entity
     */
    addChild(entity: Entity): Entity;
    /**
     * Remove an entity from children if it exists
     * @param entity
     */
    removeChild(entity: Entity): Entity;
    /**
     * Removes all children from this entity
     */
    removeAllChildren(): Entity;
    /**
     * Returns a list of parent entities starting with the topmost parent. Includes the current entity.
     */
    getAncestors(): Entity[];
    /**
     * Returns a list of all the entities that descend from this entity. Includes the current entity.
     */
    getDescendants(): Entity[];
    /**
     * Creates a deep copy of the entity and a copy of all its components
     */
    clone(): Entity;
    /**
     * Adds a copy of all the components from another template entity as a "prefab"
     * @param templateEntity Entity to use as a template
     * @param force Force component replacement if it already exists on the target entity
     */
    addTemplate(templateEntity: Entity, force?: boolean): Entity;
    private _getClassHierarchyRoot;
    /**
     * Adds a component to the entity
     * @param component Component or Entity to add copy of components from
     * @param force Optionally overwrite any existing components of the same type
     */
    addComponent<TComponent extends Component>(component: TComponent, force?: boolean): Entity<TKnownComponents | TComponent>;
    /**
     * Removes a component from the entity, by default removals are deferred to the end of entity update to avoid consistency issues
     *
     * Components can be force removed with the `force` flag, the removal is not deferred and happens immediately
     * @param typeOrInstance
     * @param force
     */
    removeComponent<TComponent extends Component>(typeOrInstance: ComponentCtor<TComponent> | TComponent, force?: boolean): Entity<Exclude<TKnownComponents, TComponent>>;
    clearComponents(): void;
    /**
     * @hidden
     * @internal
     */
    processComponentRemoval(): void;
    /**
     * Check if a component type exists
     * @param type
     */
    has<TComponent extends Component>(type: ComponentCtor<TComponent>): boolean;
    private _isInitialized;
    private _isAdded;
    /**
     * Gets whether the actor is Initialized
     */
    get isInitialized(): boolean;
    get isAdded(): boolean;
    /**
     * Initializes this entity, meant to be called by the Scene before first update not by users of Excalibur.
     *
     * It is not recommended that internal excalibur methods be overridden, do so at your own risk.
     * @internal
     */
    _initialize(engine: Engine): void;
    /**
     * Adds this Actor, meant to be called by the Scene when Actor is added.
     *
     * It is not recommended that internal excalibur methods be overridden, do so at your own risk.
     * @internal
     */
    _add(engine: Engine): void;
    /**
     * Removes Actor, meant to be called by the Scene when Actor is added.
     *
     * It is not recommended that internal excalibur methods be overridden, do so at your own risk.
     * @internal
     */
    _remove(engine: Engine): void;
    /**
     * It is not recommended that internal excalibur methods be overridden, do so at your own risk.
     *
     * Internal _preupdate handler for {@apilink onPreUpdate} lifecycle event
     * @internal
     */
    _preupdate(engine: Engine, elapsed: number): void;
    /**
     * It is not recommended that internal excalibur methods be overridden, do so at your own risk.
     *
     * Internal _preupdate handler for {@apilink onPostUpdate} lifecycle event
     * @internal
     */
    _postupdate(engine: Engine, elapsed: number): void;
    /**
     * `onInitialize` is called before the first update of the entity. This method is meant to be
     * overridden.
     *
     * Synonymous with the event handler `.on('initialize', (evt) => {...})`
     */
    onInitialize(engine: Engine): void;
    /**
     * `onAdd` is called when Actor is added to scene. This method is meant to be
     * overridden.
     *
     * Synonymous with the event handler `.on('add', (evt) => {...})`
     */
    onAdd(engine: Engine): void;
    /**
     * `onRemove` is called when Actor is added to scene. This method is meant to be
     * overridden.
     *
     * Synonymous with the event handler `.on('remove', (evt) => {...})`
     */
    onRemove(engine: Engine): void;
    /**
     * Safe to override onPreUpdate lifecycle event handler. Synonymous with `.on('preupdate', (evt) =>{...})`
     *
     * `onPreUpdate` is called directly before an entity is updated.
     */
    onPreUpdate(engine: Engine, elapsed: number): void;
    /**
     * Safe to override onPostUpdate lifecycle event handler. Synonymous with `.on('postupdate', (evt) =>{...})`
     *
     * `onPostUpdate` is called directly after an entity is updated.
     */
    onPostUpdate(engine: Engine, elapsed: number): void;
    /**
     *
     * Entity update lifecycle, called internally
     * @internal
     * @param engine
     * @param elapsed
     */
    update(engine: Engine, elapsed: number): void;
    emit<TEventName extends EventKey<EntityEvents>>(eventName: TEventName, event: EntityEvents[TEventName]): void;
    emit(eventName: string, event?: any): void;
    on<TEventName extends EventKey<EntityEvents>>(eventName: TEventName, handler: Handler<EntityEvents[TEventName]>): Subscription;
    on(eventName: string, handler: Handler<unknown>): Subscription;
    once<TEventName extends EventKey<EntityEvents>>(eventName: TEventName, handler: Handler<EntityEvents[TEventName]>): Subscription;
    once(eventName: string, handler: Handler<unknown>): Subscription;
    off<TEventName extends EventKey<EntityEvents>>(eventName: TEventName, handler: Handler<EntityEvents[TEventName]>): void;
    off(eventName: string, handler: Handler<unknown>): void;
    off(eventName: string): void;
}
