import { Group, Box3, BufferGeometry, Mesh, Vector3, Plane, Raycaster, Quaternion, Object3D, Matrix4, Vector2, Face, PlaneGeometry } from 'three';
import { TransformControls } from '../TransformControls.js';
import { OBB } from 'three/examples/jsm/math/OBB.js';
import { type IViewer } from '../../../IViewer.js';
import { CameraController } from '../CameraController.js';
import { Vector3Like } from '../../batching/BatchObject.js';
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2.js';
import SpeckleStandardMaterial from '../../materials/SpeckleStandardMaterial.js';
import { Extension } from '../Extension.js';
export declare enum SectionToolEvent {
    DragStart = "section-box-drag-start",
    DragEnd = "section-box-drag-end",
    Updated = "section-box-changed"
}
export interface SectionToolEventPayload {
    [SectionToolEvent.DragStart]: void;
    [SectionToolEvent.DragEnd]: void;
    [SectionToolEvent.Updated]: Plane[];
}
export declare class SectionTool extends Extension {
    protected cameraProvider: CameraController;
    get inject(): (typeof CameraController)[];
    /** Configurable rotation snap angle in radians. Set to null to disable snapping */
    rotationSnapAngle: number | null;
    /** Note: Rotation snapping only applies to mouse interactions via TransformControls.
     *  Programmatic calls to setBox() will not apply rotation snapping.
     *  For complete snapping support, programmatic rotations will need to be handled separately.
     */
    /** This is our data model. All we need is an OBB */
    protected obb: OBB;
    /** The planes that will send out as clipping planes */
    protected planes: Plane[];
    /** The six planes of the unit cube */
    protected localPlanes: Plane[];
    /** Convenience LUT for when clicking on the box faces */
    protected cubeFaces: {
        '256': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '152': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '407': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '703': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '327': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '726': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '450': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '051': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '312': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '013': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '546': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
        '647': {
            verts: number[];
            axis: string;
            normal: Vector3;
        };
    };
    /** The root object  */
    protected display: Group;
    /** We only use this for hit testing to select it's faces */
    protected boxHitMesh: Mesh;
    /** The displayed box as an outline */
    protected boxOutline: LineSegments2;
    /** Mesh that gets shown across a box face when it gets selected */
    protected facePlane: Mesh;
    /** Anchor objects for the controls. Not displayable */
    protected translationRotationAnchor: Object3D;
    protected scaleAnchor: Object3D;
    /** Controls instances */
    protected translateControls: TransformControls;
    protected rotateControls: TransformControls;
    protected scaleControls: TransformControls;
    /** Sum state */
    protected lastScale: Vector3 | null;
    protected lastObbTransform: Matrix4;
    protected draggingFace: Face | null;
    /** Hit testing related */
    protected raycaster: Raycaster;
    protected dragging: boolean;
    protected shiftKeyPressed: boolean;
    protected keydownHandler: (e: KeyboardEvent) => void;
    protected keyupHandler: (e: KeyboardEvent) => void;
    protected sectionBoxHistory: OBB[];
    protected currentHistoryIndex: number;
    protected maxHistorySize: number;
    /** Manadatory property for all extensions */
    get enabled(): boolean;
    set enabled(value: boolean);
    /** Hides all controls and the box outline but keeps the sections enabled */
    get visible(): boolean;
    set visible(value: boolean);
    /** Gets the up to date section planes */
    get sectionPlanes(): Plane[];
    /**
     *
     */
    constructor(viewer: IViewer, cameraProvider: CameraController);
    /**
     *
     */
    /** We use the viewer's frame update to enable/disable the translate and rotate controls
     *  The controls were not meant to be overlayed and working in multiple instance setups
     *  so their input events overlap. It's not the best solution in the world, but it's one
     *  that requires little to no source change
     */
    onEarlyUpdate(): void;
    /** Explicit events for the selection tool */
    on<T extends SectionToolEvent>(eventType: T, listener: (arg: SectionToolEventPayload[T]) => void): void;
    /** Gets the OBB model */
    getBox(): OBB;
    /**
     * Sets the OBB model and updates the tool gizmos and box
     * @param targetBox The box to set. It accepts an aabb as well
     * @param offset Optional offset
     */
    setBox(targetBox: OBB | Box3 | {
        min: Vector3Like;
        max: Vector3Like;
    }, offset?: number): void;
    /**
     * Convenience method
     */
    toggle(): void;
    /** Gets the transformation defined by the OBB */
    getObbTransform(): Matrix4;
    /**
     * Creates the controls and all their gizmos
     */
    protected setupControls(): void;
    /**
     * Creates an OBB state from the current OBB
     */
    protected createObbState(): OBB;
    /**
     * Applies an OBB state to the current OBB
     */
    protected applyObbState(state: OBB): void;
    /**
     * Saves the current section box state to history
     */
    protected saveToHistory(): void;
    /**
     * Sets up keyboard event listeners for shift key rotation snapping and undo/redo
     */
    protected setupKeyboardListeners(): void;
    /**
     * Controls, outline and hitbox update based on the OBB model
     */
    protected updateVisual(): void;
    /**
     * Triggers when transform interactions start/stop
     * @param event Controls event
     */
    protected draggingHandler(event: any): void;
    /** Triggers whenever there is a change in the controls and their gizmos
     *  This is where the model OBB gets updated according to controls changes.
     *  Each control type writes it's data in the anchor's matching property. So:
     *  - Translate control write to it's anchor 'position'
     *  - Rotate control writes to it's anchor 'quaternion'
     *  - Scale control writes to it's anchor 'scale
     */
    protected changeHandler(): void;
    /**
     * Handler used for detecting when we click on the box faces
     * @param args NDC pointer coords + original event + multiselect
     * @returns
     */
    protected clickHandler(args: Vector2 & {
        event: PointerEvent;
        multiSelect: boolean;
    }): void;
    /**
     * Computes the final box planes from the unit cube planes
     * transformed against the current OBB model
     */
    protected updatePlanes(): void;
    /**
     * Creates the plane mesh that will be shown when selecting a box face
     * It's RTE enabled
     */
    protected createFacePlane(): Mesh<PlaneGeometry, SpeckleStandardMaterial>;
    /**
     * Updates the scale control and plane mesh when a cube face is selected
     * @param face The face we're pulling/pushing
     * @returns void
     */
    protected updateFaceControls(face: Face | null): void;
    /** Creates the geometry for the visible outline of the section tool */
    protected createOutline(): LineSegments2;
    /** Updates the section tool outline by updating it's vertices
     *  We chose to do it this way in order have RTE working
     */
    protected updateOutline(): void;
    /** Creates a unit cube geometry instance*/
    protected createCubeGeometry(): BufferGeometry;
    /** Restes the gizmos. Honestly not sure if it does anything meaningfull */
    protected reset(): void;
    /** Type guards */
    protected isAABB(box: Box3 | {
        min: Vector3Like;
        max: Vector3Like;
    } | OBB): box is Box3;
    protected isOBB(box: Box3 | {
        min: Vector3Like;
        max: Vector3Like;
    } | OBB): box is OBB;
    /**
     * Snaps a quaternion to the nearest grid based on rotationSnapAngle.
     * This is useful for rotation snapping.
     * @param q The quaternion to snap.
     * @returns The snapped quaternion.
     */
    protected snapQuaternionToGrid(q: Quaternion): Quaternion;
    /**
     * Undoes the last section box change
     */
    protected undoSectionBox(): void;
    /**
     * Redoes the last undone section box change
     */
    protected redoSectionBox(): void;
    /**
     * Cleanup method to remove event listeners and prevent memory leaks
     */
    dispose(): void;
}
