import { AssetReference } from "../engine/engine_addressables.js";
import { Behaviour } from "./Component.js";
import { EventList } from "./EventList.js";
/**
 * {@link SceneSwitcher} event argument data
 */
export type LoadSceneEvent = {
    /**
     * The {@link SceneSwitcher} that is loading the scene
     */
    switcher: SceneSwitcher;
    /**
     * The scene that is being loaded
     */
    scene: AssetReference;
    /**
     * The index of the scene that is being loaded
     */
    index: number;
};
export type LoadSceneProgressEvent = LoadSceneEvent & {
    progress: number;
};
/**
 * The ISceneEventListener is called by the {@link SceneSwitcher} when a scene is loaded or unloaded.
 * It must be added to the root object of your scene (that is being loaded) or on the same object as the SceneSwitcher
 * It can be used to e.g. smooth the transition between scenes or to load additional content when a scene is loaded.
 * @example
 * ```ts
 * import { ISceneEventListener } from "@needle-tools/engine";
 *
 * // Add this component to the root object of a scene loaded by a SceneSwitcher or to the same object as the SceneSwitcher
 * export class MySceneListener implements ISceneEventListener {
 *   async sceneOpened(sceneSwitcher: SceneSwitcher) {
 *    console.log("Scene opened", sceneSwitcher.currentlyLoadedScene?.url);
 *  }
 * }
 * ```
 *
 **/
export interface ISceneEventListener {
    /** Called when the scene is loaded and added */
    sceneOpened(sceneSwitcher: SceneSwitcher): Promise<void>;
    /** Called before the scene is being removed (due to another scene being loaded) */
    sceneClosing(): Promise<void>;
}
/** The SceneSwitcher can be used to dynamically load and unload extra content
 * Available scenes are defined in the `scenes` array.
 * Loaded scenes will be added to the SceneSwitcher's GameObject as a child and removed when another scene is loaded by the same SceneSwitcher.
 * Live Examples
 * - [Multi Scenes Sample](https://engine.needle.tools/samples/multi-scene-example) (source code available)
 * - [Needle Website](https://needle.tools)
 * - [Songs Of Cultures](https://app.songsofcultures.com)
 *
 * ![](https://cloud.needle.tools/-/media/I-atrBcwIcg2kfvPl8c71A.gif)
 * *Replace entire scenes with the SceneSwitcher.*
 *
 * ![](https://cloud.needle.tools/-/media/_FbH-7pkDmluTdfphXlP-A.gif)
 * *Multiple SceneSwitcher components can be used at the same time and they can also be nested
 * (a scene loaded by a SceneSwitcher can also have a SceneSwitcher to load sub-scenes).*
 *
 * ### Interfaces
 * Use the {@link ISceneEventListener} interface to listen to scene open and closing events with the ability to modify transitions and stall the scene loading process.
 *
 * ### Events
 * - `loadscene-start`: Called when a scene starts loading
 * - `loadscene-finished`: Called when a scene finished loading
 * - `progress`: Called when a scene is loading and the progress changes
 * - `scene-opened`: Called when a scene is loaded and added to the SceneSwitcher's GameObject
 * @example
 * ```ts
 * sceneSwitcher.addEventListener("loadscene-start", (e) => {
 *    console.log("Loading scene", e.detail.scene.url);
 * });
 * sceneSwitcher.addEventListener("loadscene-finished", (e) => {
 *   console.log("Finished loading scene", e.detail.scene.url);
 * });
 * sceneSwitcher.addEventListener("progress", (e) => {
 *  console.log("Loading progress", e.loaded, e.total);
 * });
 * sceneSwitcher.addEventListener("scene-opened", (e) => {
 * console.log("Scene opened", e.detail.scene.url);
 * });
 * ```
 *
 * @summary Dynamically loads and switches between multiple scenes
 * @category Asset Management
 * @group Components
 * @see {@link ISceneEventListener} for scene transition callbacks
 * @see {@link AssetReference} for loading individual assets
 * @see {@link NestedGltf} for embedding static glTF content
 * @link https://engine.needle.tools/docs/how-to-guides/components/scene-switcher.html
 */
export declare class SceneSwitcher extends Behaviour {
    /** When enabled the first scene will be loaded when the SceneSwitcher becomes active
     * @default true
    */
    autoLoadFirstScene: boolean;
    /**
     * The scenes that can be loaded by the SceneSwitcher.
     * @default []
     */
    scenes: AssetReference[];
    /**
     * The scene that is displayed while a scene is loading.
     * @default undefined
     */
    loadingScene?: AssetReference;
    /** the url parameter that is set/used to store the currently loaded scene in, set to "" to disable
     * @default "scene"
    */
    queryParameterName: string;
    /**
     * when enabled the scene name will be used as the query parameter (otherwise the scene index will be used)
     * Needs `queryParameterName` set
     * @default true
     */
    useSceneName: boolean;
    /**
     * When enabled the current scene index will be clamped to the scenes array bounds.
     * For example when the last scene is loaded and `clamp` is true then trying to load the `next()` scene will not change the scene.
     * When `clamp` is false and the last scene is loaded then the first scene will be loaded instead.
     * @default true
     */
    clamp: boolean;
    /** when enabled the new scene is pushed to the browser navigation history, only works with a valid query parameter set
     * @default true
    */
    useHistory: boolean;
    /** when enabled you can switch between scenes using keyboard left, right, A and D or number keys
     * @default true
    */
    useKeyboard: boolean;
    /** when enabled you can switch between scenes using swipe (mobile only)
     * @default true
    */
    useSwipe: boolean;
    /** when enabled will automatically apply the environment scene lights
     * @default true
    */
    useSceneLighting: boolean;
    /** When enabled will automatically apply the skybox from the loaded scene
     * @default true
     */
    useSceneBackground: boolean;
    /** how many scenes after the currently active scene should be preloaded
     * @default 1
    */
    preloadNext: number;
    /** how many scenes before the currently active scene should be preloaded
     * @default 1
    */
    preloadPrevious: number;
    /** how many scenes can be loaded in parallel
     * @default 2
    */
    preloadConcurrent: number;
    /**
     * When enabled will create a button for the Needle menu to switch to the next or previous scene
     * @default false
     */
    createMenuButtons: boolean;
    /** The index of the currently loaded and active scene */
    get currentIndex(): number;
    /** Get the progress of the currently loading scene. This is undefined if no scene is loading
     * You can also subscribe to the loading event by adding an event listener to the scene switcher.
     * For example like this `sceneSwitcher.addEventListeneer("progress", (e) => {...})`
     */
    get currentLoadingProgress(): ProgressEvent<EventTarget> | undefined;
    /** The currently loading scene. This is undefined if no scene is loading. */
    get currentlyLoadingScene(): AssetReference | undefined;
    /**
     * The currently loaded scene. This is undefined if no scene is loaded.
     */
    get currentlyLoadedScene(): AssetReference | undefined;
    /**
     * Called when a scene starts loading
     */
    sceneLoadingStart: EventList<LoadSceneEvent>;
    sceneLoadingProgress: EventList<ProgressEvent>;
    /**
     * The sceneLoaded event is called when a scene/glTF is loaded and added to the scene
     */
    sceneLoaded: EventList<SceneSwitcher>;
    private _currentIndex;
    private _currentScene;
    private _currentSceneAsset;
    private _engineElementOverserver;
    private _preloadScheduler?;
    private _menuButtons?;
    private __lastSwitchScene?;
    private __lastSwitchScenePromise?;
    /** @internal */
    awake(): void;
    /** @internal */
    onEnable(): Promise<void>;
    /** @internal */
    onDisable(): void;
    private onPopState;
    private normalizedSwipeThresholdX;
    private _didSwipe;
    private onInputPointerMove;
    private onInputPointerUp;
    private onInputKeyDown;
    /**
     * Add a scene to the SceneSwitcher.
     * If the scene is already added it will be added again.
     * @param urlOrAssetReference The url of the scene or an AssetReference to the scene
     * @returns The AssetReference of the scene that was added
     * @example
     * ```ts
     * // adding a scene:
     * sceneSwitcher.addScene("scene1.glb");
     * // add another scene and load it:
     * const scene2 = sceneSwitcher.addScene("scene2.glb");
     * sceneSwitcher.switchScene(scene2).then(res => { console.log("Scene loaded", res); });
     * ```
     */
    addScene(urlOrAssetReference: string | AssetReference): AssetReference;
    /**
     * Load the next scene in the scenes array ({@link this.currentIndex} + 1)
     * If the current scene is the last scene in the array and {@link this.clamp} is disabled then the first scene will be loaded.
     * @returns a promise that resolves to true if the scene was loaded successfully
     */
    selectNext(): Promise<boolean>;
    /**
     * Load the previous scene in the scenes array ({@link this.currentIndex} - 1)
     * If the current scene is the first scene in the array and {@link this.clamp} is disabled then the last scene will be loaded.
     * @returns a promise that resolves to true if the scene was loaded successfully
     */
    selectPrev(): Promise<boolean>;
    /**
     * Load a scene by its index in the scenes array.
     * @param index The index of the scene or a string that represents the scene uri (if the url is not known to the SceneSwitcher it will try to load the scene by its uri but it won't be added to the current scenes array. Use {@link addScene} to add a scene to the SceneSwitcher)
     * @returns a promise that resolves to true if the scene was loaded successfully
     */
    select(index: number | string): Promise<boolean>;
    /**
     * Unload the currently loaded scene.
     */
    unload(): Promise<void>;
    /**
     * Reload the last scene that was loaded
     * @returns a promise that resolves to true if the scene was loaded successfully
     */
    reload(): Promise<boolean>;
    /**
     * Switch to a scene by its AssetReference.
     * If the scene is already loaded it will be unloaded and the new scene will be loaded.
     * If the scene is already loading it will wait for the scene to be loaded.
     * If the scene is already loaded and the same scene is requested again it will return the same promise that was returned the first time the scene was requested.
     * @param scene The AssetReference of the scene to switch to
     * @returns a promise that resolves to true if the scene was loaded successfully
     * @example
     * ```ts
     * const myAssetReference = new AssetReference("scene1.glb");
     * sceneSwitcher.switchScene(myAssetReference).then(res => { console.log("Scene loaded", res); });
     * ```
     */
    switchScene(scene: AssetReference): Promise<boolean>;
    private __unloadCurrentScene;
    private _currentlyLoadingScene?;
    /** @internal */
    private __internalSwitchScene;
    preload(index: number): Promise<boolean> | Promise<ArrayBufferLike | null>;
    private tryLoadFromQueryParam;
    /** try to select a scene from a string or index */
    private trySelectSceneFromValue;
    private _lastLoadingScene;
    private _loadingScenePromise;
    private _isCurrentlyLoading;
    private _currentLoadingProgress;
    private onStartLoading;
    private onEndLoading;
    private tryGetSceneEventListener;
}
