import { Group, Box3, BufferGeometry, Mesh, Vector3, Plane, Raycaster, 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)[];
    /** 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;
    /** 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;
    /**
     * Controls, outline and hitbox update based on the OBB model
     */
    protected updateVisual(): void;
    /**
     * Triggers when dragging starts/stops
     * @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;
}
