import { vertexvis } from '@vertexvis/frame-streaming-protos';
import { BoundingBox, Vector3 } from '@vertexvis/geometry';
import { StreamApi } from '@vertexvis/stream-api';
import { FrameDecoder } from '../mappers';
import { Animation, ClippingPlanes, FlyTo, FrameCamera, FrameCameraBase, FrameOrthographicCamera, FramePerspectiveCamera, StandardView } from '../types';
import { CameraRenderResult } from './cameraRenderResult';
import ISceneItemQueryExpression = vertexvis.protobuf.stream.ISceneItemQueryExpression;
export interface CameraRenderOptions {
    animation?: Animation.Animation;
}
export declare class TerminalFlyToExecutor {
    private flyToOptions?;
    constructor(flyToOptions?: FlyTo.FlyToOptions | undefined);
    build(): FlyTo.FlyToOptions | undefined;
}
export declare class FlyToExecutor {
    private flyToOptions?;
    withItemId(id: string): TerminalFlyToExecutor;
    withSuppliedId(id: string): TerminalFlyToExecutor;
    withCamera(camera: FrameCamera.FrameCamera): TerminalFlyToExecutor;
    withBoundingBox(boundingBox: BoundingBox.BoundingBox): TerminalFlyToExecutor;
    build(): FlyTo.FlyToOptions | undefined;
}
export interface FlyToParams {
    itemId?: string;
    camera?: FrameCamera.FrameCamera;
    boundingBox?: BoundingBox.BoundingBox;
    itemSuppliedId?: string;
    sceneItemQueryExpression?: ISceneItemQueryExpression;
}
/**
 * The `Camera` class contains properties that reflect a world space position, a
 * view direction (lookAt), and normalized vector representing the up direction.
 *
 * It also provides utility methods to update orientation of the camera and
 * rerender the scene.
 *
 * This class in intended to be treated as an immutable type. Any mutations return
 * a new instance of the class with the updated properties.
 */
export declare abstract class Camera {
    protected stream: StreamApi;
    protected aspect: number;
    private data;
    protected boundingBox: BoundingBox.BoundingBox;
    protected decodeFrame: FrameDecoder;
    protected flyToOptions?: FlyTo.FlyToOptions | undefined;
    constructor(stream: StreamApi, aspect: number, data: FrameCamera.FrameCamera, boundingBox: BoundingBox.BoundingBox, decodeFrame: FrameDecoder, flyToOptions?: FlyTo.FlyToOptions | undefined);
    /**
     * Updates the position of the camera such that the given bounding box will
     * be contained within the camera's view.
     *
     * @param boundingBox The bounding box to position to.
     */
    fitToBoundingBox(boundingBox: BoundingBox.BoundingBox): Camera;
    /**
     * Returns the distance from the camera's position to the center
     * of the provided bounding box (or the scene's visible bounding box if not provided).
     *
     * @param boundingBox - The bounding box to determine distance from.
     */
    signedDistanceToBoundingBoxCenter(boundingBox?: BoundingBox.BoundingBox): number;
    /**
     * Specifies that the next render of the camera will be repositioned to one of
     * the options specified in `options`.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector("vertex-viewer");
     * const scene = await viewer.scene();
     * const camera = scene.camera();
     *
     * // Fly to and fit to a specific item by ID with an animation of 1 second
     * await camera
     *   .flyTo({ itemId: "item-id" })
     *   .render({ animation: { milliseconds: 1000 } });
     *
     * // Fly to and fit to a specific item by supplied ID with an animation of 1 second
     * await camera
     *   .flyTo({ itemSuppliedId: "item-supplied-id" })
     *   .render({ animation: { milliseconds: 1000 } });
     *
     * // Fly to and fit to the bounding box of the current set of selected items
     * // with an animation of 1 second
     * await camera
     *   .flyTo({
     *     boundingBox:
     *       viewer.frame.scene.sceneViewSummary.selectedVisibleSummary.boundingBox,
     *   })
     *   .render({ animation: { milliseconds: 1000 } });
     *
     * // Fly to a specific camera
     * await camera
     *   .flyTo({
     *     camera: {
     *       position: {
     *         x: 1,
     *         y: 2,
     *         z: 3,
     *       },
     *       lookAt: {
     *         x: 0,
     *         y: 0,
     *         z: 0,
     *       },
     *       up: {
     *         x: 0,
     *         y: 1,
     *         z: 0,
     *       },
     *     },
     *   })
     *   .render({ animation: { milliseconds: 1000 } });
     *
     * // Fly to scene items specified by a query
     * await camera
     *   .flyTo({
     *     sceneItemQueryExpression: {
     *       operand: {
     *         metadata: {
     *           valueFilter: 'WheelHub',
     *           keys: ['ProductName'],
     *         },
     *       },
     *     },
     *   })
     * ```
     *
     * @param paramsOrQuery An object or query describing how the camera should
     * be positioned.
     */
    flyTo(paramsOrQuery: FlyToParams | ((q: FlyToExecutor) => TerminalFlyToExecutor)): Camera;
    /**
     * Performs a `flyTo` operation with the current visible bounding box of
     * the scene.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     * const scene = await viewer.scene();
     * const camera = scene.camera();
     *
     * // Fit to the visible bounding box of the scene with an animation of 1 second
     * await camera.viewAll().render({ animation: { milliseconds: 1000 } });
     * ```
     */
    viewAll(): Camera;
    /**
     * Queues the rendering for a new frame using this camera. The returned
     * promise will resolve when a frame is received that contains this camera.
     */
    render(renderOptions?: CameraRenderOptions): Promise<CameraRenderResult>;
    /**
     * Repositions the camera by rotating its current position around an axis placed
     * at the `lookAt` point. This method internally will call {@link Camera.rotateAroundAxisAtPoint}
     * with the `point` parameter set to the current `lookAt` point.
     *
     * @see {@link Camera.rotateAroundAxisAtPoint} for more information.
     *
     * @param angleInRadians The angle, in radians, to rotate.
     * @param axis A normalized vector to rotate around.
     */
    rotateAroundAxis(angleInRadians: number, axis: Vector3.Vector3): Camera;
    /**
     * Aligns the camera to the plane defined by the provided position and normal.
     * This will place the camera at the provided position, set the up vector to
     * the provided normal, and place the lookAt on the defined plane. The point
     * chosen for the lookAt will be determined using the current view vector.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector("vertex-viewer");
     *
     * viewer.addEventListener("tap", async (event) => {
     *   const scene = await viewer.scene();
     *   const raycaster = scene.raycaster();
     *
     *   const [hit] = await raycaster.hitItems(event.detail.position);
     *
     *   if (hit != null) {
     *     const camera = scene.camera();
     *
     *     // Align to the plane represented by the hit result with an animation of 1 second
     *     await camera
     *       .alignTo(hit.hitPoint, hit.hitNormal)
     *       .render({ animation: { milliseconds: 1000 } });
     *   }
     * });
     * ```
     *
     * @param position The position to place the camera at.
     * @param normal The normal of the plane to align to.
     */
    alignTo(position: Vector3.Vector3, normal: Vector3.Vector3): Camera;
    /**
     * Updates the `position` and `up` vectors of the camera to the given standard
     * view, and sets the `lookAt` point to the origin.
     *
     * @see {@link StandardView} for the available standard views.
     *
     * @param standardView The standard view to apply.
     * @returns A new camera.
     */
    standardView(standardView: StandardView): Camera;
    /**
     * Updates the `position` and `up` vectors of the camera to the given standard
     * view, maintaining the existing `lookAt` point.
     *
     * @see {@link StandardView} for the available standard views.
     *
     * @param standardView The standard view to apply.
     * @returns A new camera.
     */
    standardViewFixedLookAt(standardView: StandardView): Camera;
    private buildFlyToType;
    protected computeClippingPlanes(camera: FrameCamera.FrameCamera): ClippingPlanes.ClippingPlanes;
    /**
     * Repositions the camera by rotating its current position around an axis
     * defined at a specific world point.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector('vertex-viewer');
     *
     * viewer.addEventListener('tap', async (event) => {
     *   const scene = await viewer.scene();
     *   const raycaster = scene.raycaster();
     *
     *   const [hit] = await raycaster.hitItems(event.detail.position);
     *
     *   if (hit != null) {
     *     const camera = scene.camera();
     *
     *     // Using the current `up` vector of the camera, rotate 45 degrees
     *     // about the hit position with an animation of 1 second
     *     await camera.rotateAroundAxisAtPoint(
     *       Angle.toRadians(45),
     *       hit.hitPoint,
     *       camera.up,
     *     ).render({ animation: { milliseconds: 1000 } });
     *   }
     * });
     * ```
     *
     * @param angleInRadians The angle, in radians, to rotate.
     * @param point The point in world space to place the axis at.
     * @param axis A normalized vector to rotate around.
     */
    abstract rotateAroundAxisAtPoint(angleInRadians: number, point: Vector3.Vector3, axis: Vector3.Vector3): Camera;
    abstract get position(): Vector3.Vector3;
    abstract get lookAt(): Vector3.Vector3;
    abstract get up(): Vector3.Vector3;
    abstract get near(): number;
    abstract get far(): number;
    abstract get aspectRatio(): number;
    abstract get viewVector(): Vector3.Vector3;
    /**
     * Shifts the position of the camera by the given delta.
     *
     * @param delta The number of units to shift the camera on the X, Y, and Z
     * axis.
     */
    abstract moveBy(delta: Vector3.Vector3): Camera;
    /**
     * Updates the `position`, `lookAt` and/or `up` vectors of the camera. Each
     * vector can be omitted in the payload, and the resulting camera will keep
     * the previous `position`, `lookAt`, or `up` vectors.
     *
     * @example
     * ```typescript
     * const viewer = document.querySelector("vertex-viewer");
     * const scene = await viewer.scene();
     * const camera = scene.camera();
     *
     * // Update the camera to place it at the origin
     * await camera
     *   .update({
     *     position: {
     *       x: 0,
     *       y: 0,
     *       z: 0,
     *     },
     *   })
     *   .render({ animation: { milliseconds: 1000 } });
     *
     * // Update the camera to look at the origin
     * await camera
     *   .update({
     *     lookAt: {
     *       x: 0,
     *       y: 0,
     *       z: 0,
     *     },
     *   })
     *   .render({ animation: { milliseconds: 1000 } });
     * ```
     *
     * @param camera The values to update the camera to.
     */
    abstract update(camera: Partial<FrameCamera.FrameCamera>): Camera;
    /**
     * Returns a `FrameCameraBase` representation.
     */
    abstract toFrameCamera(): FrameCameraBase;
    protected abstract updateFlyToOptions(flyToOptions?: FlyTo.FlyToOptions): Camera;
}
export declare class PerspectiveCamera extends Camera implements FrameCamera.PerspectiveFrameCamera {
    private perspectiveData;
    constructor(stream: StreamApi, aspect: number, perspectiveData: FrameCamera.PerspectiveFrameCamera, boundingBox: BoundingBox.BoundingBox, decodeFrame: FrameDecoder, flyToOptions?: FlyTo.FlyToOptions);
    /**
     * Shifts the position of the camera by the given delta.
     *
     * @param delta The number of units to shift the camera on the X, Y, and Z
     * axis.
     */
    moveBy(delta: Vector3.Vector3): Camera;
    rotateAroundAxisAtPoint(angleInRadians: number, point: Vector3.Vector3, axis: Vector3.Vector3): Camera;
    update(camera: Partial<FrameCamera.PerspectiveFrameCamera>): Camera;
    toFrameCamera(): FramePerspectiveCamera;
    get viewVector(): Vector3.Vector3;
    /**
     * The position vector for the camera, in world space coordinates.
     */
    get position(): Vector3.Vector3;
    /**
     * A normalized vector representing the up direction.
     */
    get up(): Vector3.Vector3;
    /**
     * A vector, in world space coordinates, of where the camera is pointed at.
     */
    get lookAt(): Vector3.Vector3;
    /**
     * The camera's field of view.
     */
    get fovY(): number | undefined;
    /**
     * The aspect ratio of the camera.
     */
    get aspectRatio(): number;
    /**
     * The camera's near clipping plane.
     */
    get near(): number;
    /**
     * The camera's far clipping plane.
     */
    get far(): number;
    protected updateFlyToOptions(flyToOptions?: FlyTo.FlyToOptions): PerspectiveCamera;
}
export declare class OrthographicCamera extends Camera implements FrameCamera.OrthographicFrameCamera {
    private orthographicData;
    constructor(stream: StreamApi, aspect: number, orthographicData: FrameCamera.OrthographicFrameCamera, boundingBox: BoundingBox.BoundingBox, decodeFrame: FrameDecoder, flyToOptions?: FlyTo.FlyToOptions);
    /**
     * Shifts the position of the camera by the given delta.
     *
     * @param delta The number of units to shift the camera on the X, Y, and Z
     * axis.
     */
    moveBy(delta: Vector3.Vector3): Camera;
    rotateAroundAxisAtPoint(angleInRadians: number, point: Vector3.Vector3, axis: Vector3.Vector3): Camera;
    update(camera: Partial<FrameCamera.FrameCamera>): Camera;
    toFrameCamera(): FrameOrthographicCamera;
    get viewVector(): Vector3.Vector3;
    get position(): Vector3.Vector3;
    /**
     * A vector, in world space coordinates, of where the camera should be rotated around.
     * Most interactions (like pan and zoom) will update lookAt and rotationPoint to be the same point.
     * However, rotation interactions will only update lookAt and not rotationPoint.
     */
    get rotationPoint(): Vector3.Vector3 | undefined;
    /**
     * A normalized vector representing the up direction.
     */
    get up(): Vector3.Vector3;
    /**
     * A vector, in world space coordinates, of where the camera is pointed at.
     */
    get lookAt(): Vector3.Vector3;
    /**
     * The camera's field of view.
     */
    get fovHeight(): number;
    /**
     * The aspect ratio of the camera.
     */
    get aspectRatio(): number;
    /**
     * The camera's near clipping plane.
     */
    get near(): number;
    /**
     * The camera's far clipping plane.
     */
    get far(): number;
    protected updateFlyToOptions(flyToOptions?: FlyTo.FlyToOptions): OrthographicCamera;
}
