import { XRDevice } from 'iwer';
import { Camera, Object3D, WebXRManager } from 'three';
import { StoreApi } from 'zustand/vanilla';
import { XRControllerLayoutLoaderOptions } from './controller/index.js';
import { XRHandLoaderOptions } from './hand/index.js';
import { XRSessionInitOptions } from './init.js';
import { XRInputSourceState, XRInputSourceStateMap } from './input.js';
import { XRLayerEntry } from './layer.js';
import type { EmulatorOptions } from './emulate.js';
declare global {
    export interface XRSessionEventMap {
        trackedsourceschange: XRInputSourcesChangeEvent;
    }
    export interface XRSession {
        trackedSources?: ReadonlyArray<XRInputSource>;
    }
}
declare global {
    type XRBodyJoint = 'root' | 'hips' | 'spine-lower' | 'spine-middle' | 'spine-upper' | 'chest' | 'neck' | 'head' | 'left-shoulder' | 'left-scapula' | 'left-arm-upper' | 'left-arm-lower' | 'left-hand-wrist-twist' | 'right-shoulder' | 'right-scapula' | 'right-arm-upper' | 'right-arm-lower' | 'right-hand-wrist-twist' | 'left-hand-palm' | 'left-hand-wrist' | 'left-hand-thumb-metacarpal' | 'left-hand-thumb-phalanx-proximal' | 'left-hand-thumb-phalanx-distal' | 'left-hand-thumb-tip' | 'left-hand-index-metacarpal' | 'left-hand-index-phalanx-proximal' | 'left-hand-index-phalanx-intermediate' | 'left-hand-index-phalanx-distal' | 'left-hand-index-tip' | 'left-hand-middle-metacarpal' | 'left-hand-middle-phalanx-proximal' | 'left-hand-middle-phalanx-intermediate' | 'left-hand-middle-phalanx-distal' | 'left-hand-middle-tip' | 'left-hand-ring-metacarpal' | 'left-hand-ring-phalanx-proximal' | 'left-hand-ring-phalanx-intermediate' | 'left-hand-ring-phalanx-distal' | 'left-hand-ring-tip' | 'left-hand-little-metacarpal' | 'left-hand-little-phalanx-proximal' | 'left-hand-little-phalanx-intermediate' | 'left-hand-little-phalanx-distal' | 'left-hand-little-tip' | 'right-hand-palm' | 'right-hand-wrist' | 'right-hand-thumb-metacarpal' | 'right-hand-thumb-phalanx-proximal' | 'right-hand-thumb-phalanx-distal' | 'right-hand-thumb-tip' | 'right-hand-index-metacarpal' | 'right-hand-index-phalanx-proximal' | 'right-hand-index-phalanx-intermediate' | 'right-hand-index-phalanx-distal' | 'right-hand-index-tip' | 'right-hand-middle-metacarpal' | 'right-hand-middle-phalanx-proximal' | 'right-hand-middle-phalanx-intermediate' | 'right-hand-middle-phalanx-distal' | 'right-hand-middle-tip' | 'right-hand-ring-metacarpal' | 'right-hand-ring-phalanx-proximal' | 'right-hand-ring-phalanx-intermediate' | 'right-hand-ring-phalanx-distal' | 'right-hand-ring-tip' | 'right-hand-little-metacarpal' | 'right-hand-little-phalanx-proximal' | 'right-hand-little-phalanx-intermediate' | 'right-hand-little-phalanx-distal' | 'right-hand-little-tip' | 'left-upper-leg' | 'left-lower-leg' | 'left-foot-ankle-twist' | 'left-foot-ankle' | 'left-foot-subtalar' | 'left-foot-transverse' | 'left-foot-ball' | 'right-upper-leg' | 'right-lower-leg' | 'right-foot-ankle-twist' | 'right-foot-ankle' | 'right-foot-subtalar' | 'right-foot-transverse' | 'right-foot-ball';
    interface XRBodySpace extends XRSpace {
        readonly jointName: XRBodyJoint;
    }
    interface XRBody extends Map<XRBodyJoint, XRBodySpace> {
    }
    interface XRFrame {
        readonly body?: XRBody;
    }
}
export type XRState<T extends XRElementImplementations> = Readonly<{
    body?: XRBody;
    /**
     * current `XRSession`
     */
    session?: XRSession;
    mediaBinding?: XRMediaBinding;
    /**
     * `XRReferenceSpace` of the origin in the current session
     * (this references to the session origin at the floor level)
     */
    originReferenceSpace?: XRReferenceSpace;
    /**
     * the 3D object representing the session origin
     * if the origin is undefined it is implicitly at world position 0,0,0
     */
    origin?: Object3D;
    /**
     * the HTML element for doing dom overlays in handheld AR experiences
     */
    domOverlayRoot?: Element;
    /**
     * the session visibility state
     * e.g. `"visible-blurred"` typically occurs when the user sees an OS overlay
     */
    visibilityState?: XRVisibilityState;
    /**
     * the configured xr framerate
     * caution: the actual framerate of the experience may be lower if it cannot keep up
     */
    frameRate?: number;
    /**
     * the xr session mode
     */
    mode: XRSessionMode | null;
    /**
     * all xr input sources
     */
    inputSourceStates: ReadonlyArray<XRInputSourceState>;
    /**
     * the detected `XRPlane`s
     */
    detectedPlanes: ReadonlyArray<XRPlane>;
    /**
     * the detected `XRMesh`es
     */
    detectedMeshes: ReadonlyArray<XRMesh>;
    /**
     * active additional webxr layers
     */
    layerEntries: ReadonlyArray<XRLayerEntry>;
    /**
     * access to the emulator values to change the emulated input device imperatively
     */
    emulator?: XRDevice;
} & WithRecord<T>>;
export type XRElementImplementations = {
    [Key in keyof XRInputSourceStateMap]: unknown;
};
export type WithRecord<T extends XRElementImplementations> = {
    /**
     * options for configuring the <DefaultXRController/> or provide your own controller implementation
     * options and implementations can be provided for each handedness individually `{ left: false, right: { ... } }`
     * @example { rayPointer: false, grabPointer: { cursorModel: { color: "red" } } }
     * `false` prevents these controllers from beeing used
     * @default true
     */
    controller: T['controller'] | ({
        [Key in XRHandedness]?: T['controller'];
    } & {
        default?: T['controller'];
    });
    /**
     * options for configuring the <DefaultXRTransientPointer/> or provide your own transient pointer implementation
     * options and implementations can be provided for each handedness individually `{ left: false, right: { ... } }`
     * `false` prevents these transient pointers from beeing used
     * @example { rayPointer: { cursorModel: { color: "red" } } }
     * @default true
     */
    transientPointer: T['transientPointer'] | ({
        [Key in XRHandedness]?: T['transientPointer'];
    } & {
        default?: T['transientPointer'];
    });
    /**
     * options for configuring the <DefaultXRHand/> or provide your own hand implementation
     * options and implementations can be provided for each handedness individually `{ left: false, right: { ... } }`
     * `false` prevents these hands from beeing used
     * @example { rayPointer: false, grabPointer: { cursorModel: { color: "red" } } }
     * @default true
     */
    hand: T['hand'] | ({
        [Key in XRHandedness]?: T['hand'];
    } & {
        default?: T['hand'];
    });
    /**
     * options for configuring the <DefaultXRGaze/> or provide your own gaze implementation
     * @example { rayPointer: { cursorModel: { color: "red" } } }
     * `false` prevents these controllers from beeing used
     * @default true
     */
    gaze: T['gaze'];
    /**
     * options for configuring the <DefaultXRScreenInput/> or provide your own screen input implementation
     * @example { rayPointer: { cursorModel: { color: "red" } } }
     * `false` prevents these controllers from beeing used
     * @default true
     */
    screenInput: T['screenInput'];
};
export declare function resolveInputSourceImplementation<T extends object | Function>(implementation: undefined | T | ({
    [Key in XRHandedness]?: T | boolean;
} & {
    default?: T | boolean;
}) | boolean, handedness: XRHandedness | undefined, defaultValue: T | false): T | false;
export type FrameBufferScalingOption = undefined | number | ((maxFrameBufferScaling: number) => number | undefined) | 'high' | 'mid' | 'low';
export type FrameRateOption = ((supportedFrameRates: ArrayLike<number>) => number | false) | 'high' | 'mid' | 'low' | false;
export type XRStoreOptions<T extends XRElementImplementations> = {
    /**
     * Automatically makes a session request to the browser which can provide a custom ui for the user to start the XR experience.
     * if set to `true` the system will request an "immersive-ar" session if supported, else an "immersive-vr" session
     * @default true
     */
    offerSession?: XRSessionMode | boolean;
    /**
     * emulates a device if WebXR not supported and on localhost
     * @default "metaQuest3"
     */
    emulate?: EmulatorOptions | boolean;
    /**
     * sets the WebXR foveation between 0 and 1
     * undefined refers to the default foveation provided by the device/browser
     * @default undefined
     */
    foveation?: number;
    /**
     * sets the framerate of the session
     * @default "high"
     */
    frameRate?: FrameRateOption;
    /**
     * sets the framebuffer scaling of the session
     * undefined refers to the default framebuffer scaling provided by the device/browser (e.g. 1)
     * @default undefined
     */
    frameBufferScaling?: FrameBufferScalingOption;
    /**
     * session modes that can be entered automatically without manually requesting a session when granted by the system
     * @default true
     */
    enterGrantedSession?: boolean | Array<XRSessionMode>;
    /**
     * allows to use non primary (tracked) input sources
     * @default false
     */
    secondaryInputSources?: boolean;
} & XRControllerLayoutLoaderOptions & XRHandLoaderOptions & Partial<WithRecord<T>> & XRSessionInitOptions;
export type XRStore<T extends XRElementImplementations> = Omit<StoreApi<XRState<T>>, 'destroy'> & {
    /**
     * add webxr layer entry
     */
    addLayerEntry(entry: XRLayerEntry): void;
    /**
     * remove webxr layer entry
     */
    removeLayerEntry(entry: XRLayerEntry): void;
    /**
     * internal function
     */
    setWebXRManager(xr: WebXRManager): void;
    /**
     * internal function
     */
    onBeforeFrame(scene: Object3D, camera: Camera, frame: XRFrame | undefined): void;
    /**
     * internal function
     */
    onBeforeRender(): void;
    /**
     * destroys the store unrepairably (for exiting XR use store.getState().session?.end())
     */
    destroy(): void;
    enterXR(mode: XRSessionMode): Promise<XRSession | undefined>;
    enterAR(): Promise<XRSession | undefined>;
    enterVR(): Promise<XRSession | undefined>;
    /**
     * update the hand configuration or implementation for both or only one hand
     */
    setHand(implementation: T['hand'], handedness?: XRHandedness): void;
    /**
     * update the controller configuration or implementation for both or only one controller
     */
    setController(implementation: T['controller'], handedness?: XRHandedness): void;
    /**
     * update the gaze configuration or implementation
     */
    setGaze(implementation: T['gaze']): void;
    /**
     * update the screen input configuration or implementation
     */
    setScreenInput(implementation: T['screenInput']): void;
    /**
     * update the transient pointer configuration or implementation for both or only one hand
     */
    setTransientPointer(implementation: T['transientPointer'], handedness?: XRHandedness): void;
    setFrameRate(value: FrameRateOption): void;
    /**
     * returns a promise that resolves on the next render with the xr frame
     */
    requestFrame(): Promise<XRFrame>;
};
declare module 'three' {
    interface Object3D {
        xrSpace?: XRSpace;
    }
}
declare global {
    interface XRSystem {
        offerSession?: XRSystem['requestSession'];
    }
}
export declare function createXRStore<T extends XRElementImplementations>(options?: XRStoreOptions<T>): XRStore<T>;
