import { Box3, BufferGeometry, Color, InstancedMesh, type Material, Matrix4, Object3D, Vector3 } from "three";
import { type LineMaterial } from "three/examples/jsm/Addons";
import { type BufferElement } from "../..";
/**
 * Special alpha value to mark selected instances for fast outline detection.
 * Note: Instanced meshes use a separate instanceSelected attribute instead of alpha.
 */
export declare const SELECTION_ALPHA = 0.99;
export declare class ViralInstancedMeshV2 extends Object3D {
    protected material?: Material | undefined;
    private static readonly _tempMatrix4A;
    private static readonly _tempVec3A;
    private static readonly _tempMatrix4B;
    private static readonly _tempBox3A;
    globalMaterialIndex: number;
    private _depthPrePassMeshes;
    constructor(material?: Material | undefined);
    protected _instancedMeshes: Map<string, InstancedMesh<BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>, Material | Material[], import("three").InstancedMeshEventMap>>;
    _bufferElements: BufferElement[];
    protected _originalColor: Color | null;
    protected _elementMap: Map<string, Map<string, {
        geometryKey: string;
        instanceIndex: number;
        instancedMesh: InstancedMesh;
    }[]>>;
    private _originalTransforms;
    private _elementOpacity;
    private _temporaryColors;
    private _ghostColors;
    private _selectedElements;
    private _hidingElements;
    protected _isolatingElements: {
        modelId: string;
        elementId: string;
    }[];
    private _edgeLines;
    private _edgeRanges;
    private _edgeThreshold;
    private _edgeMaterial;
    private _isGeneratedLights;
    private _pointLight;
    addBufferElements(bufferElements: BufferElement[], materialColor: Color): void;
    private rebuildInstances;
    private _createInstancedMesh;
    protected _createGeometryFromBuffer(buffer: Float32Array): BufferGeometry;
    protected _transformArrayToMatrix4(transform: number[]): Matrix4;
    protected _generateGeometryKey(buffer: Float32Array): string;
    batch(newBufferElements: BufferElement[]): void;
    select(elements: {
        modelId: string;
        elementId: string;
    }[], excepts?: {
        elements: {
            modelId: string;
            elementId: string;
        }[];
        color: {
            r: number;
            g: number;
            b: number;
        };
    }[]): void;
    unselect(): void;
    /**
     * Set instance selection state for fast outline detection
     * @param elements - Elements to set selection for
     * @param selected - 1.0 = selected, 0.0 = not selected
     */
    private _setInstanceSelection;
    /**
     * Changes the color of multiple elements.
     * @param elements - An array of elements, each containing `modelId` and `elementId`.
     * @param color - The new RGB color to apply
     * @param isTemporary - If true, stores this color as a temporary layer that will be restored on reset
     *
     * @example
     * ```typescript
     * // Normal color change (resets to original)
     * mesh.changeColor([{ modelId: "0", elementId: "abc" }], { r: 1, g: 0, b: 0 });
     *
     * // Temporary color (resets to this color instead of original)
     * mesh.changeColor([{ modelId: "0", elementId: "abc" }], { r: 0, g: 1, b: 0 }, true);
     * ```
     */
    changeColor(elements: {
        modelId: string;
        elementId: string;
    }[], color: {
        r: number;
        g: number;
        b: number;
    }, isTemporary?: boolean): void;
    /**
     * Clears temporary colors for specified elements or all elements
     * @param elements - Elements to clear temporary colors for, or null to clear all
     */
    clearTemporaryColors(elements?: {
        modelId: string;
        elementId: string;
    }[] | null): void;
    /**
     * Resets the color of elements back to temporary color (if exists) or original color.
     * @param elements - Array of elements to reset, or `null` to reset all instances.
     * @param excepts - Elements that should receive a different color instead of original/temporary
     *
     * @example
     * ```typescript
     * // Reset all elements to temporary color (if set) or original color
     * mesh.resetColor(null);
     *
     * // Reset specific elements
     * mesh.resetColor([{ modelId: "0", elementId: "abc" }, { modelId: "0", elementId: "def" }]);
     * ```
     */
    resetColor(elements: {
        modelId: string;
        elementId: string;
    }[] | null, excepts?: {
        elements: {
            modelId: string;
            elementId: string;
        }[];
        color: {
            r: number;
            g: number;
            b: number;
        };
    }[]): void;
    get selectedElements(): {
        modelId: string;
        elementId: string;
    }[];
    get hidingElements(): {
        modelId: string;
        elementId: string;
    }[];
    get isolatingElements(): {
        modelId: string;
        elementId: string;
    }[];
    /** Per-element opacity map. Key: "modelId:elementId", Value: opacity number. */
    get elementOpacity(): ReadonlyMap<string, number>;
    /** Temporary colors map. Key: "modelId:elementId". */
    get temporaryColors(): ReadonlyMap<string, {
        r: number;
        g: number;
        b: number;
    }>;
    /** Ghost colors map. Key: "modelId:elementId". */
    get ghostColors(): ReadonlyMap<string, {
        r: number;
        g: number;
        b: number;
    }>;
    /** Set of hidden element keys ("modelId:elementId"). */
    get hiddenSet(): ReadonlySet<string>;
    /** Set of isolated element keys ("modelId:elementId"). */
    get isolatedSet(): ReadonlySet<string>;
    private _hiddenSet;
    private _isolatedSet;
    private static readonly ZERO_MATRIX;
    /**
     * Hide elements by setting their transform scale to 0
     * Zero-scaled instances are automatically culled by GPU - maximum performance
     *
     * @param elements - Elements to hide (defaults to selected elements)
     */
    hide(elements?: {
        modelId: string;
        elementId: string;
    }[]): void;
    /**
     * Isolate elements - show ONLY these elements, hide everything else
     * Uses batch matrix update for best performance
     *
     * @param elements - Elements to isolate (defaults to selected elements)
     * @returns The isolated elements
     */
    isolate(elements?: {
        modelId: string;
        elementId: string;
    }[]): {
        modelId: string;
        elementId: string;
    }[];
    /**
     * Isolate entire models
     * @param modelIds - Model IDs to isolate
     */
    isolateModel(modelIds: string[]): void;
    /**
     * Show a previously hidden element
     * @param elements - Elements to show
     */
    show(elements: {
        modelId: string;
        elementId: string;
    }[]): void;
    /**
     * Reset all visibility - show everything
     */
    reset(): void;
    /**
     * Check if an element is currently visible
     */
    isElementVisible(modelId: string, elementId: string): boolean;
    /**
     * Inject per-instance opacity and selection shader into material
     * Enables:
     * - Per-instance opacity (ghosting, hiding)
     * - Selection alpha marker (for fast outline detection via AlphaSelectionOutlinePass)
     * Must be called after material is set and before rendering
     */
    injectOpacityShader(): void;
    /**
     * Ensure all instanced meshes have opacity attribute
     */
    private _ensureOpacityAttributes;
    /**
     * Ensure all instanced meshes have selection attribute
     * Used for fast outline detection via AlphaSelectionOutlinePass
     */
    private _ensureSelectionAttributes;
    /**
     * Update opacity for specific instances
     */
    private _updateInstanceOpacity;
    /**
     * Set opacity for specific elements
     * @param elements - Elements to set opacity for
     * @param opacity - Opacity value (0-1)
     */
    setElementOpacity(elements: {
        modelId: string;
        elementId: string;
    }[], opacity: number): void;
    /**
     * Get current opacity of an element
     * @param modelId - Model ID
     * @param elementId - Element ID
     * @returns Current opacity (0-1), defaults to 1
     */
    getElementOpacity(modelId: string, elementId: string): number;
    /**
     * Set elements to "ghost" mode (semi-transparent)
     * @param elements - Elements to ghost
     * @param ghostOpacity - Opacity for ghosted elements (default 0.1)
     * @param desaturate - Whether to desaturate color (default: true) - ignored if ghostColor is provided
     * @param ghostColor - Optional custom color for ghosted elements (e.g., {r: 1, g: 1, b: 1} for white)
     */
    setElementGhost(elements: {
        modelId: string;
        elementId: string;
    }[], ghostOpacity?: number, desaturate?: boolean, ghostColor?: {
        r: number;
        g: number;
        b: number;
    }): void;
    /**
     * Ghost all elements EXCEPT the specified ones
     * @param elements - Elements to keep fully opaque
     * @param ghostOpacity - Opacity for all other elements (default 0.1)
     * @param ghostColor - Optional custom color for ghosted elements (e.g., {r: 1, g: 1, b: 1} for white)
     */
    ghostExcept(elements: {
        modelId: string;
        elementId: string;
    }[], ghostOpacity?: number, ghostColor?: {
        r: number;
        g: number;
        b: number;
    }): void;
    /**
     * Create depth-only pre-pass instanced meshes that write depth for focused instances.
     * Shares the same geometry (including instanceOpacity attribute); uses shader discard
     * to skip ghost instances (opacity < 0.5).
     */
    private _createDepthPrePass;
    /**
     * Remove and dispose all depth pre-pass meshes
     */
    private _removeDepthPrePass;
    /**
     * Desaturate instance color (turn whitish)
     * @param modelId - Model ID
     * @param elementId - Element ID
     * @param desatFactor - Desaturation factor (0 = original, 1 = full white)
     */
    private _desaturateInstanceColor;
    /**
     * Set instance color to a specific color
     * @param modelId - Model ID
     * @param elementId - Element ID
     * @param color - Target color {r, g, b} with values 0-1
     */
    private _setInstanceColor;
    /**
     * Restore instance color to original
     */
    private _restoreInstanceColor;
    /**
     * Reset all elements to full opacity and restore original colors
     */
    resetElementOpacity(): void;
    /**
     * Check if any element has semi-transparent opacity
     */
    hasTransparentElements(): boolean;
    /**
     * Check if MOST elements are transparent (for deciding depth write strategy)
     * Returns true if more than 50% of elements have transparency
     */
    private _isMostlyTransparent;
    /**
     * 🔧 Update material depth write based on transparency state
     * When MOST elements are semi-transparent, disable depth write
     * Also respects originally transparent materials (windows, glass)
     */
    private _updateDepthWriteForTransparency;
    enableEdgePerElement(material: LineMaterial, thresholdDeg?: number): void;
    disableEdge(): void;
    enableEdge(): void;
    refreshEdgesIfAny(): void;
    private _buildInstancedEdges;
    isolateEdge(elements?: {
        modelId: string;
        elementId: string;
    }[]): void;
    hideEdge(elements?: {
        modelId: string;
        elementId: string;
    }[]): void;
    edgeReset(): void;
    /**
     * Enable raycasting for all instanced meshes
     */
    enableRaycasting(): void;
    /**
     * Custom raycast function for instanced meshes
     */
    private _instancedRaycast;
    findElementByInstancedMeshAndIndex(instancedMesh: InstancedMesh, instanceIndex: number): {
        modelId: string;
        elementId: string;
    } | null;
    /**
     * Alternative method: Find element by face index (similar to original)
     * Note: This is more complex for instanced meshes
     */
    findElementByFaceIndex(faceIndex: number): {
        modelId: string;
        elementId: string;
    } | null;
    /**
     * Get all instanced meshes for external raycast handling
     */
    getInstancedMeshes(): InstancedMesh[];
    getElements(elements: {
        modelId: string;
        elementId: string;
    }[]): BufferElement[];
    getElementsByModel(modelIndex: number): BufferElement[];
    getElementBoxs(elements: {
        modelId: string;
        elementId: string;
    }[]): Box3 | null;
    getTotalVertexCount(): number;
    getObjectCount(): number;
    get isBatching(): boolean;
    enableLights(): void;
    disableLights(): void;
    calculateCenter(buffer: Float32Array): Vector3 | null;
    private getFarthestDistance;
    dispose(): void;
}
