import { EventEmitter } from "eventemitter3";
import type * as THREE from "three";
import { CoreContextModule } from "./CoreContextModule";
import { IFeaturable } from "./Object3DFeaturablity";
import { ThreeContext, ThreeContextParams } from "./ThreeContext";
export type ModulesRecord = Record<string, CoreContextModule>;
export type ModulesRecordDefault = Record<string, CoreContextModule & Record<string, any>>;
/**
 * The primary central entity, acting as a main hub, that orchestrates the Three.js environment, animation loop, and module system.\
 * Propagates through features `Object3DFeature` which are added to Three.js `Object3D`.\
 * Provides an elegant lifecycle management system and handles fundametal initializations.
 * @see {@link https://three-kvy-core.vladkrutenyuk.ru/docs/api/core-context | Official Documentation}
 * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/core/CoreContext.ts | Source}
 */
export declare class CoreContext<TModules extends ModulesRecord = ModulesRecordDefault> extends EventEmitter<{
    destroy: [];
    looprun: [];
    loopstop: [];
}> {
    /**
     * Initialization shortcut. Creates and returns a new {@link CoreContext} instance.
     * @param {typeof import("three")} Three - Object containing Three.js class constructors `WebGLRenderer`, `Scene`, `PerspectiveCamera`, `Clock`, `Raycaster`. In short, just use imported [`THREE`](https://threejs.org/docs/manual/en/introduction/Installation.html) Three.js module.
     * @param {TModules} modules - (optional) Custom dictionary of any your modules {@link CoreContextModules}.
     * @param {ThreeContextParams} params - (optional) Object paramateres
     * @example
     * ```js
     *	import * as THREE from "three";
     *	import * as KVY from "@vladkrutenyuk/three-kvy-core";
     *
     *	const modules = {
     *		moduleA: new MyModuleA(),
     *		moduleB: new MyModuleB(),
     *	};
     *	const ctx = KVY.CoreContext.create(THREE, modules, { renderer: { antialias: true } });
     *	```
     * @returns {CoreContext}
     */
    static create<TModules extends ModulesRecord = ModulesRecordDefault>(Three: {
        Scene: typeof THREE.Scene;
        WebGLRenderer: typeof THREE.WebGLRenderer;
        PerspectiveCamera: typeof THREE.PerspectiveCamera;
        Raycaster: typeof THREE.Raycaster;
        Clock: typeof THREE.Clock;
    }, modules?: Partial<TModules>, params?: ThreeContextParams): CoreContext<TModules>;
    /** (readonly) Flag to mark that it is an instance of {@link CoreContext}. */
    readonly isCoreContext: true;
    /** (readonly) Instance of {@link ThreeContext}. Utility to manage Three.js setup. */
    readonly three: ThreeContext;
    /** (readonly) Dictionary of assinged modules.
     * @type { { [key:string]: CoreContextModule } }
     */
    readonly modules: TModules;
    /**
     * (readonly) Instance of Three.js `Object3D` that plays the role of entry point for a given context propagation.\
     * By default, it's Three.js `Scene` instance given in `ThreeContext` of this (`this.root === this.three.scene`).\
     * You can specify any other `root` if you initialize the context through constructor.
     * @type {THREE.Object3D}
     * */
    get root(): IFeaturableRoot<TModules>;
    /** (readonly) The seconds passed since the last frame. */
    get deltaTime(): number;
    /** (readonly) The seconds passed since the context loop started - by {@link run run()}. */
    get time(): number;
    /** (readonly) Flag to check if this instance is destroyed.  */
    get isDestroyed(): boolean;
    /** (readonly) Flag to check if this instance loop is running. */
    get isRunning(): boolean;
    private readonly _root;
    private readonly _clock;
    private _time;
    private _deltaTime;
    private _isDestroyed;
    private _isRunning;
    /**
     * This creates a new {@link CoreContext} instance.
     * @param three - An instance of {@link ThreeContext}. Utility to manage Three.js setup.
     * @param {THREE.Object3D} root - (optional) An instance of Three.js `Object3D`. The entry point for context propagation. If root is not providen then Three.js `Scene` from the given {@link ThreeContext} will be taken as root.
     * @param {TModules} modules - (optional) Custom dictionary of any your modules {@link CoreContextModules}.
     */
    constructor(three: ThreeContext, root?: THREE.Object3D, modules?: Partial<TModules>);
    /** Run animation loop and Three.js rendering. Stoppable as many times as you need by `stop()`. */
    run(): void;
    /** Stop animation loop and Three.js rendering. Resumable as many times as you need by `run()`. */
    stop(): void;
    private _cleanups;
    /**
     * Assigns the given dictionary of modules to this instance.
     * It will be merged with the existing dictionary of modules.
     *
     * @remarks Note that if the given dictionary contains a key for which a module is already assigned,
     * it will be skipped, and a warning message will be fired.
     *
     * @param {{ [key: string]: CoreContextModule }} modules - Dictionary of module instances to assign to this context.
     */
    assignModules(modules: Partial<TModules>): this;
    /**
     * Assign module by key to this instance.
     * It will be added to the existing dictionary of modules by the given key.
     *
     * @remarks Note that if the given key is already assigned, it will be skipped, and a warning message will be fired.
     * @param {string} key - The key by which to assign the module to the context in the dictionary.
     * @param {CoreContextModule} module - An instance of `CoreContextModule` implementation.
     * @returns
     */
    assignModule<TKey extends keyof TModules>(key: TKey, module: TModules[TKey]): void;
    /**
     * Remove a module by key that was specified when it was assigned.
     * @param {string} key - key by which a module was assigned.
     */
    removeModule(key: keyof TModules): void;
    /**
     * Destroy this instance.
     * - Sets {@link isDestroyed} to `true` permanently.
     * - Stops its animation loop permanently.
     * - Destroys its {@link three three}: {@link ThreeContext} permanently.
     * - Fires the `"destroy"` event.
     * - Cleans up {@link root} from the assigned logic when it was designated as `root` in the given CoreContext.
     * - Removes all assigned {@link modules}.
     * - Removes all listeners from its events.
     */
    destroy(): this;
}
export interface IFeaturableRoot<TModules extends ModulesRecord = any> extends IFeaturable<TModules> {
    isRoot: true;
}
