import type { Bento } from '../Bento';
import { InstanceType } from '../types/InstanceType';
import { EntityEvents } from './EntityEvents';
import { ReferenceManager } from './ReferenceManager';
import { Component } from './interfaces/Component';
import { Entity, EntityType } from './interfaces/Entity';
import { Plugin } from './interfaces/Plugin';
import { ComponentReference } from './types/ComponentReference';
import { EntityReference } from './types/EntityReference';
import { PluginReference } from './types/PluginReference';
export declare enum PluginHook {
    PRE_COMPONENT_LOAD = "onPreComponentLoad",
    PRE_COMPONENT_UNLOAD = "onPreComponentUnload",
    POST_COMPONENT_LOAD = "onPostComponentLoad",
    POST_COMPONENT_UNLOAD = "onPostComponentUnload"
}
export interface PendingEntityInfo {
    name: string;
    entity: Entity;
    missing: Array<EntityReference>;
}
export declare class EntityManager {
    private readonly bento;
    private readonly events;
    private readonly entities;
    private readonly pending;
    private readonly references;
    constructor(bento: Bento);
    resolveReference(reference: EntityReference, error?: boolean): ReturnType<ReferenceManager<Entity>['resolve']>;
    /**
     * Check if EntityEvents exists
     * @param reference EntityReference
     *
     * @returns boolean
     */
    hasEvents(reference: EntityReference): boolean;
    /**
     * Get EntityEvents or create it
     * @param reference EntityReference
     *
     * @returns EntityEvents
     */
    getEvents(reference: EntityReference): EntityEvents;
    /**
     * Get loaded entities
     * @param type EntityType
     *
     * @returns Entity Map
     */
    getEntities<T extends Entity>(type?: EntityType): Map<string, T>;
    /**
     * Check if Entity exists
     * @param reference EntityReference
     *
     * @returns boolean
     */
    hasEntity(reference: EntityReference): boolean;
    /**
     * Get Entity
     * @param reference EntityReference
     *
     * @returns Entity or null
     */
    getEntity<T extends Entity>(reference: EntityReference<T>): T;
    /**
     * Add a Entity to Bento
     * @param entity - Entity
     *
     * @returns Entity name
     */
    addEntity(entity: Entity | InstanceType<Entity>): Promise<string>;
    /**
     * Replace entity and rewrite references and name behind the scenes.
     *
     * This allows for the following code to work:
     * ```ts
     * class Old { name = 'old'; replaceable = true }
     * class New { name = 'new' }
     *
     * await bento.replaceEntity(Old, new New());
     *
     * bento.getEntity(Old); // Would actually return Instance of the New class
     * ```
     *
     * @param reference EntityReference
     * @param entity Entity
     */
    replaceEntity(reference: EntityReference, entity: Entity | InstanceType<Entity>): Promise<string>;
    /**
     * Remove a Entity from Bento
     * @param reference - Name of Entity
     */
    removeEntity(reference: EntityReference): Promise<Array<Entity>>;
    /**
     * Check if Plugin exists
     * @param reference PluginReference
     *
     * @returns boolean
     */
    hasPlugin(reference: PluginReference): boolean;
    /**
     * Get all Plugins
     *
     * @returns Plugin Map
     */
    getPlugins(): Map<string, Plugin>;
    /**
     * Get Plugin
     * @param reference PluginReference
     *
     * @returns Plugin or null
     */
    getPlugin<T extends Plugin>(reference: PluginReference<T>): T;
    /**
     * Adds plugins in order of array
     * @param plugins - array of plugins
     *
     * @returns Array of loaded plugin names
     */
    addPlugins(plugins: Array<Plugin | InstanceType<Plugin>>): Promise<Array<string>>;
    addPlugin(plugin: Plugin | InstanceType<Plugin>): Promise<string>;
    replacePlugin(reference: PluginReference, plugin: Plugin | InstanceType<Plugin>): Promise<string>;
    removePlugin(plugin: PluginReference): Promise<Array<Entity>>;
    /**
     * Check if Component exists
     * @param reference ComponentReference
     *
     * @returns boolean
     */
    hasComponent(reference: ComponentReference): boolean;
    /**
     * Get all Components
     *
     * @returns Component Map
     */
    getComponents(): Map<string, Component>;
    /**
     * Adds components in order of array
     * @param components - array of plugins
     *
     * @returns Array of loaded plugin names
     */
    addComponents(components: Array<Component | InstanceType<Component>>): Promise<Array<string>>;
    /**
     * Get Component
     * @param reference ComponentReference
     *
     * @returns Component or null
     */
    getComponent<T extends Component>(reference: ComponentReference<T>): T;
    /**
     * Add Component
     * @param component Component
     *
     * @returns Component Name
     */
    addComponent(component: Component | InstanceType<Component>): Promise<string>;
    /**
     * Replace Component
     * @param reference ComponentReference
     * @param component Component
     *
     * @returns Component Name
     */
    replaceComponent(reference: ComponentReference, component: Component | InstanceType<Component>): Promise<string>;
    /**
     * Remove Component
     * @param reference ComponentReference
     *
     * @returns Removed Entities
     */
    removeComponent(reference: ComponentReference): Promise<Array<Entity>>;
    /**
     * Verify loaded entites & call their onVerify() hook
     * @returns Map of string/Entity pairs
     */
    verify(): Promise<Map<string, Entity>>;
    /**
     * @see PendingEntityInfo
     * @returns - All currently pending bento entities and their info
     */
    getPendingEntities(): Array<PendingEntityInfo>;
    /**
     * Get all dependents of a entity
     * @param entity - EntityReference
     *
     * @returns Array of Entities
     */
    getEntityDependents<T extends Entity>(entity: EntityReference): Array<T>;
    /**
     * Get missing depenencies of an Entity
     * @param reference EntityReference
     *
     * @returns EntityReference Array
     */
    getMissingDependencies(entityOrReference: Entity | EntityReference): Array<EntityReference>;
    /**
     * Ensures all entity dependencies resolve to a name, and no duplicates
     * @param entity Entity
     */
    private resolveDependencies;
    /**
     * Handle pending entities
     *
     * @returns Promise
     */
    private handlePendingEntities;
    /**
     * Prepare Decorators
     * @param entity Entity
     */
    private prepareDecorators;
    /**
     * Handle Decorators
     * @param entity Entity
     */
    private handleDecorators;
    /**
     * Enforces Bento API and prepares entity for loading
     * @param entity - Entity
     */
    private prepareEntity;
    /**
     * Load Entity into Bento or deffer for dependencies
     * @param entity Entity
     *
     * @returns Entity Name
     */
    private loadEntity;
    /**
     * Handle Entity Lifecycle
     * @param entity Entity
     */
    private handleLifecycle;
    /**
     * Call Hook for all plugins
     * @param hookName Hook name
     * @param component Component
     */
    private handlePluginHook;
}
