import { Quaternion, Vector3 } from "three";
import { Context } from "../engine_context.js";
import type { IComponent, INeedleXRSession } from "../engine_types.js";
import { NeedleXRController } from "./NeedleXRController.js";
import { NeedleXRSync } from "./NeedleXRSync.js";
import { SceneTransition } from "./SceneTransition.js";
import type { IXRRig } from "./XRRig.js";
/** @link https://developer.mozilla.org/en-US/docs/Web/API/XRFrame/fillPoses */
declare type FillPosesFunction = (spaces: IterableIterator<XRJointSpace>, referenceSpace: XRSpace, targetArray: Float32Array) => void;
declare type NeedleXRFrame = XRFrame & {
    fillPoses?: FillPosesFunction;
};
/** NeedleXRSession event argument.
 * Use `args.xr` to access the NeedleXRSession */
export type NeedleXREventArgs = {
    readonly xr: NeedleXRSession;
};
export type SessionChangedEvt = (args: NeedleXREventArgs) => void;
export type SessionRequestedEvent = (args: {
    readonly mode: XRSessionMode;
    readonly init: XRSessionInit;
}) => void;
export type SessionRequestedEndEvent = (args: {
    readonly mode: XRSessionMode;
    readonly init: XRSessionInit;
    newSession: XRSession | null;
}) => void;
/** Result of a XR hit-test
 * @property {XRHitTestResult} hit The original XRHitTestResult
 * @property {Vector3} position The hit position in world space
 * @property {Quaternion} quaternion The hit rotation in world space
 */
export type NeedleXRHitTestResult = {
    readonly hit: XRHitTestResult;
    readonly position: Vector3;
    readonly quaternion: Quaternion;
};
export interface INeedleXRSessionEventReceiver extends Pick<IComponent, "destroyed"> {
    get activeAndEnabled(): boolean;
    supportsXR?(mode: XRSessionMode): boolean;
    /** Called before requesting a XR session */
    onBeforeXR?(mode: XRSessionMode, args: XRSessionInit): void;
    onEnterXR?(args: NeedleXREventArgs): void;
    onUpdateXR?(args: NeedleXREventArgs): void;
    onLeaveXR?(args: NeedleXREventArgs): void;
    onXRControllerAdded?(args: NeedleXRControllerEventArgs): void;
    onXRControllerRemoved?(args: NeedleXRControllerEventArgs): void;
}
/** Contains a reference to the currently active webxr session and the controller that has changed */
export type NeedleXRControllerEventArgs = NeedleXREventArgs & {
    controller: NeedleXRController;
    change: "added" | "removed";
};
/** Event Arguments when a controller changed event is invoked (added or removed)
 * Access the controller via `args.controller`, the `args.change` property indicates if the controller was added or removed
*/
export type ControllerChangedEvt = (args: NeedleXRControllerEventArgs) => void;
/**
 * This class manages an XRSession to provide helper methods and events. It provides easy access to the XRInputSources (controllers and hands)
 * - Start a XRSession with `NeedleXRSession.start(...)`
 * - Stop a XRSession with `NeedleXRSession.stop()`
 * - Access a running XRSession with `NeedleXRSession.active`
 *
 * If a XRSession is active you can use all XR-related event methods on your components to receive XR events e.g. `onEnterXR`, `onUpdateXR`, `onLeaveXR`
 * ```ts
 * export class MyComponent extends Behaviour {
 *    // callback invoked whenever the XRSession is started or your component is added to a scene with an active XRSession
 *    onEnterXR(args: NeedleXREventArgs) {
 *       console.log("Entered XR");
 *      // access the NeedleXRSession via args.xr
 *    }
 *    // callback invoked whenever a controller is added (or you switch from controller to hand tracking)
 *    onControllerAdded(args: NeedleXRControllerEventArgs) {  }
 * }
 * ```
 *
 * ### XRRig
 * The XRRig can be accessed via the `rig` property
 * Set a custom XRRig via `NeedleXRSession.addRig(...)` or `NeedleXRSession.removeRig(...)`
 * By default the active XRRig with the highest priority in the scene is used
 *
 * ### Screenshots in XR
 * Screenshots work automatically during XR sessions, including AR camera feed compositing. See {@link screenshot2} for more information.
 *
 * @category XR
 * @see {@link screenshot2} for taking screenshots in XR sessions
 */
export declare class NeedleXRSession implements INeedleXRSession {
    private static _sync;
    static getXRSync(context: Context): NeedleXRSync;
    static get currentSessionRequest(): XRSessionMode | null;
    private static _currentSessionRequestMode;
    /**
     * @returns the active @type {NeedleXRSession} (if any active) or null
     */
    static get active(): NeedleXRSession | null;
    /** The active xr session mode (if any xr session is active)
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSessionMode
    */
    static get activeMode(): XRSessionMode | null;
    /** XRSystem via navigator.xr access
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSystem
     */
    static get xrSystem(): XRSystem | undefined;
    /**
     * @returns true if the browser supports WebXR (`immersive-vr` or `immersive-ar`)
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSystem/isSessionSupported
     */
    static isXRSupported(): Promise<boolean>;
    /**
     * @returns true if the browser supports immersive-vr (WebXR)
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSystem/isSessionSupported
     */
    static isVRSupported(): Promise<boolean>;
    /**
     * @returns true if the browser supports immersive-ar (WebXR)
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSystem/isSessionSupported
    */
    static isARSupported(): Promise<boolean>;
    /**
     * @param mode The XRSessionMode to check if it is supported
     * @returns true if the browser supports the given XRSessionMode
     */
    static isSessionSupported(mode: XRSessionMode): Promise<boolean>;
    private static _currentSessionRequest?;
    private static _activeSession;
    /** Register to listen to XRSession start events. Unsubscribe with `offXRSessionStart` */
    static onSessionRequestStart(evt: SessionRequestedEvent): void;
    /** Unsubscribe from request start evt. Register with `onSessionRequestStart` */
    static offSessionRequestStart(evt: SessionRequestedEvent): void;
    private static readonly _sessionRequestStartListeners;
    /** Called after the session request has finished */
    static onSessionRequestEnd(evt: SessionRequestedEndEvent): void;
    /** Unsubscribe from request end evt */
    static offSessionRequestEnd(evt: SessionRequestedEndEvent): void;
    private static readonly _sessionRequestEndListeners;
    /** Listen to XR session started. Unsubscribe with `offXRSessionStart` */
    static onXRSessionStart(evt: SessionChangedEvt): void;
    /** Unsubscribe from XRSession started events */
    static offXRSessionStart(evt: SessionChangedEvt): void;
    private static readonly _xrStartListeners;
    /** Listen to XR session ended. Unsubscribe with `offXRSessionEnd` */
    static onXRSessionEnd(evt: SessionChangedEvt): void;
    /** Unsubscribe from XRSession started events */
    static offXRSessionEnd(evt: SessionChangedEvt): void;
    private static readonly _xrEndListeners;
    /** Listen to controller added events.
     * Events are cleared when starting a new session
     **/
    static onControllerAdded(evt: ControllerChangedEvt): void;
    /** Unsubscribe from controller added evts */
    static offControllerAdded(evt: ControllerChangedEvt): void;
    private static readonly _controllerAddedListeners;
    /** Listen to controller removed events
     * Events are cleared when starting a new session
     **/
    static onControllerRemoved(evt: ControllerChangedEvt): void;
    /** Unsubscribe from controller removed events */
    static offControllerRemoved(evt: ControllerChangedEvt): void;
    private static readonly _controllerRemovedListeners;
    /** If the browser supports offerSession - creating a VR or AR button in the browser navigation bar */
    static offerSession(mode: XRSessionMode, init: XRSessionInit | "default", context: Context): boolean;
    /** @returns a new XRSession init object with defaults */
    static getDefaultSessionInit(mode: Omit<XRSessionMode, "inline">): XRSessionInit;
    /** start a new webXR session (make sure to stop already running sessions before calling this method)
     * @param mode The XRSessionMode to start (e.g. `immersive-vr` or `immersive-ar`) or `ar` to start `immersive-ar` on supported devices OR on iOS devices it will export an interactive USDZ and open in Quicklook.
     * Get more information about WebXR modes: https://developer.mozilla.org/en-US/docs/Web/API/XRSessionMode
     * @param init The XRSessionInit to use (optional), docs: https://developer.mozilla.org/en-US/docs/Web/API/XRSessionInit
     * @param context The Needle Engine context to use
     */
    static start(mode: XRSessionMode | "ar" | "quicklook", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null>;
    private static invokeSessionRequestStart;
    private static invokeSessionRequestEnd;
    static setSession(mode: XRSessionMode, session: XRSession, init: XRSessionInit, context: Context): NeedleXRSession;
    private static $_stop_request;
    /** stops the active XR session */
    static stop(): void;
    private static onEnd;
    /** The needle engine context this session was started from */
    readonly context: Context;
    get sync(): NeedleXRSync | null;
    /** Returns true if the xr session is still active */
    get running(): boolean;
    /**
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSession
     */
    readonly session: XRSession;
    /** XR Session Mode: AR or VR */
    readonly mode: XRSessionMode;
    /**
     * The XRSession interface's read-only interactionMode property describes the best space (according to the user agent) for the application to draw an interactive UI for the current session.
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSession/interactionMode
     */
    get interactionMode(): "screen-space" | "world-space";
    /**
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSession/visibilityState
     * @returns {XRVisibilityState} The visibility state of the XRSession
     */
    get visibilityState(): XRVisibilityState;
    /**
     * Check if the session is `visible-blurred` - this means e.g. the keyboard is shown
     */
    get isVisibleBlurred(): boolean;
    /**
     * Check if the session has system keyboard support
     */
    get isSystemKeyboardSupported(): boolean;
    /**
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRSession/environmentBlendMode
     */
    get environmentBlendMode(): XREnvironmentBlendMode;
    /**
     * The current XR frame
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRFrame
     */
    get frame(): NeedleXRFrame;
    /** The currently active/connected controllers */
    readonly controllers: NeedleXRController[];
    /** shorthand to query the left controller. Use `controllers` to get access to all connected controllers */
    get leftController(): NeedleXRController | undefined;
    /** shorthand to query the right controller. Use `controllers` to get access to all connected controllers */
    get rightController(): NeedleXRController | undefined;
    /** @returns the given controller if it is connected */
    getController(side: XRHandedness | number): NeedleXRController | null;
    /** Returns true if running in pass through mode in immersive AR (e.g. user is wearing a headset while in AR) */
    get isPassThrough(): boolean;
    get isAR(): boolean;
    get isVR(): boolean;
    /** If the AR mode is not immersive (meaning the user is e.g. holding a phone instead of wearing a AR passthrough headset) */
    get isScreenBasedAR(): boolean;
    get posePosition(): Vector3;
    get poseOrientation(): Quaternion;
    /** @returns the context.renderer.xr.getReferenceSpace() result */
    get referenceSpace(): XRSpace | null;
    /** @returns the XRFrame `viewerpose` using the xr `referenceSpace` */
    get viewerPose(): XRViewerPose | undefined;
    /** @returns `true` if any image is currently being tracked */
    /** returns true if images are currently being tracked */
    get isTrackingImages(): boolean;
    /** The currently active XR rig */
    get rig(): IXRRig | null;
    private _rigScale;
    private _lastRigScaleUpdate;
    /** Get the XR Rig worldscale.
     *
     * **For AR**
     * If you want to modify the scale in AR at runtime get the WebARSessionRoot component via `findObjectOfType(WebARSessionRoot)` and then set the `arScale` value.
     * @returns the scale of the XR rig
     *
    */
    get rigScale(): number;
    /** add a rig to the available XR rigs - if it's priority is higher than the currently active rig it will be enabled */
    addRig(rig: IXRRig): void;
    /** Remove a rig from the available XR Rigs */
    removeRig(rig: IXRRig): void;
    /** Sets a XRRig to be active which will parent the camera to this rig */
    setRigActive(rig: IXRRig): void;
    /**
     * @returns the user position in the rig space
     */
    getUserOffsetInRig(): Vector3;
    private updateActiveXRRig;
    private _rigs;
    private _viewerHitTestSource;
    /** Returns a XR hit test result (if hit-testing is available) in rig space
     * @param source If provided, the hit test will be performed for the given controller
    */
    getHitTest(source?: NeedleXRController): NeedleXRHitTestResult | null;
    private getControllerHitTest;
    private convertHitTestResult;
    /** convert a XRRigidTransform from XR session space to threejs / Needle Engine XR space */
    convertSpace(transform: XRRigidTransform): {
        position: Vector3;
        quaternion: Quaternion;
    };
    /** this is the implictly created XR rig */
    private readonly _defaultRig;
    /** all scripts that receive some sort of XR update event */
    private readonly _xr_scripts;
    /** scripts that have onUpdateXR event methods */
    private readonly _xr_update_scripts;
    /** scripts that are in the scene but inactive (e.g. disabled parent gameObject) */
    private readonly _inactive_scripts;
    private readonly _controllerAdded;
    private readonly _controllerRemoved;
    private readonly _originalCameraWorldPosition?;
    private readonly _originalCameraWorldRotation?;
    private readonly _originalCameraWorldScale?;
    private readonly _originalCameraParent?;
    /** we store the main camera reference here each frame to make sure we have a rendering camera
     * this e.g. the case when the XR rig with the camera gets disabled (and thus this.context.mainCamera is unassigned)
     */
    private _mainCamera;
    private constructor();
    /** called when renderer.setSession is fulfilled */
    private onRendererSessionSet;
    private onInputSourceAdded;
    /** Disconnects the controller, invokes events and notifies previou controller (if any) */
    private disconnectInputSource;
    /** End the XR Session */
    end(): void;
    private _ended;
    private readonly _newControllers;
    private onEnd;
    private _didStart;
    /** Called every frame by the engine */
    private onBefore;
    private onRenderDebug;
    private onBeforeRender;
    private onAfterRender;
    /** register a new XR script if it hasnt added yet */
    private addScript;
    /** mark a script as inactive and invokes callbacks */
    private markInactive;
    private handleInactiveScripts;
    private readonly _script_to_remove;
    private removeScript;
    private invokeCallback_EnterXR;
    private invokeCallback_ControllerAdded;
    private invokeCallback_ControllerRemoved;
    private invokeCallback_LeaveXR;
    private syncCameraCullingMask;
    private invokeControllerEvent;
    private _camera;
    private readonly _cameraRenderParent;
    private _previousCameraParent;
    private readonly _customforward;
    private originalCameraNearPlane?;
    private requestedCameraNearPlane;
    /** This is used to have the XR system camera look into threejs Z forward direction (instead of -z) */
    private applyCustomForward;
    private revertCustomForward;
    private _viewerPose?;
    private readonly _transformOrientation;
    private readonly _transformPosition;
    private internalUpdateState;
    private _transition?;
    get transition(): SceneTransition;
    /** Call to fade rendering to black for a short moment (the returned promise will be resolved when fully black)
     * This can be used to mask scene transitions or teleportation
     * @returns a promise that is resolved when the screen is fully black
     * @example `fadeTransition().then(() => { <fully_black> })`
    */
    fadeTransition(): Promise<void>;
    /** e.g. FadeToBlack */
    private updateFade;
    private onUpdateFade_PostRender;
}
export {};
