/**
 * @license
 * Copyright 2025-2026 Open Home Foundation
 * SPDX-License-Identifier: Apache-2.0
 */
import { AsyncObservable, FabricId, FabricIndex, NodeId, Observable } from "@matter/main";
import { OperationalCredentials } from "@matter/main/clusters";
import { DecodedAttributeReportValue, DecodedEventReportValue } from "@matter/main/protocol";
import { EndpointNumber } from "@matter/main/types";
import { CommissioningController } from "@project-chip/matter.js";
import { NodeStates } from "@project-chip/matter.js/device";
import { AttributeResponseStatus, AttributesData, CommissioningRequest, CommissioningResponse, DiscoveryRequest, DiscoveryResponse, InvokeRequest, MatterNodeData, OpenCommissioningWindowRequest, OpenCommissioningWindowResponse, ReadEventRequest, ReadEventResponse, SubscribeAttributeRequest, SubscribeAttributeResponse, SubscribeEventRequest, SubscribeEventResponse, WriteAttributeRequest } from "../types/CommandHandler.js";
import { AccessControlEntry, AttributeWriteResult, BindingTarget, MatterSoftwareVersion, NodePingResult } from "../types/WebSocketMessageTypes.js";
export declare class ControllerCommandHandler {
    #private;
    events: {
        started: AsyncObservable<any[], void>;
        attributeChanged: Observable<[nodeId: NodeId, data: DecodedAttributeReportValue<any>], void>;
        eventChanged: Observable<[nodeId: NodeId, data: DecodedEventReportValue<any>], void>;
        nodeAdded: Observable<[nodeId: NodeId], void>;
        nodeStateChanged: Observable<[nodeId: NodeId, state: NodeStates], void>;
        /** Emitted when node availability changes (for sending node_updated events) */
        nodeAvailabilityChanged: Observable<[nodeId: NodeId, available: boolean], void>;
        nodeStructureChanged: Observable<[nodeId: NodeId], void>;
        nodeDecommissioned: Observable<[nodeId: NodeId], void>;
        nodeEndpointAdded: Observable<[nodeId: NodeId, endpointId: EndpointNumber], void>;
        nodeEndpointRemoved: Observable<[nodeId: NodeId, endpointId: EndpointNumber], void>;
    };
    constructor(controllerInstance: CommissioningController, bleEnabled: boolean, otaEnabled: boolean);
    /**
     * Format a NodeId as a PeerAddress string for logging.
     * Uses the controller's fabric index when available, otherwise "?" is used.
     */
    formatNode(nodeId: NodeId): string;
    get started(): boolean;
    get bleEnabled(): boolean;
    start(): Promise<void>;
    close(): Promise<void>;
    /**
     * Initialize the controller, register all commissioned nodes (populates attribute caches),
     * and start connecting them to the network.
     *
     * Guarded by #connected so it runs exactly once, even if called multiple times
     * (e.g. when WebServer.start() registers handlers for multiple listen addresses).
     */
    initializeNodes(): Promise<void>;
    getNodeIds(): NodeId[];
    hasNode(nodeId: NodeId): boolean;
    /**
     * Alias for decommissionNode to match NodeCommandHandler interface.
     */
    removeNode(nodeId: NodeId): Promise<void>;
    interviewNode(nodeId: NodeId): Promise<void>;
    /**
     * Get full node details in WebSocket API format.
     * @param nodeId The node ID
     * @param lastInterviewDate Optional last interview date (tracked externally)
     */
    getNodeDetails(nodeId: NodeId, lastInterviewDate?: Date): MatterNodeData;
    /**
     * Read multiple attributes from a node by path strings.
     * Supports wildcards in paths. Batches up to 9 paths per read call.
     */
    handleReadAttributes(nodeId: NodeId, attributePaths: string[], fabricFiltered?: boolean): Promise<AttributesData>;
    /**
     * Set the fabric label. Pass null or empty string to reset to "Home".
     * Note: matter.js requires non-empty labels (1-32 chars), so null/empty resets to default.
     */
    setFabricLabel(label: string): Promise<void>;
    disconnectNode(nodeId: NodeId): Promise<void>;
    handleReadEvent(data: ReadEventRequest): Promise<ReadEventResponse>;
    handleSubscribeAttribute(data: SubscribeAttributeRequest): Promise<SubscribeAttributeResponse>;
    handleSubscribeEvent(data: SubscribeEventRequest): Promise<SubscribeEventResponse>;
    handleWriteAttribute(data: WriteAttributeRequest): Promise<AttributeResponseStatus>;
    handleInvoke(data: InvokeRequest): Promise<unknown>;
    commissionNode(data: CommissioningRequest): Promise<CommissioningResponse>;
    getCommissionerNodeId(): NodeId | undefined;
    getCommissionerFabricData(): Promise<{
        fabricId: FabricId;
        compressedFabricId: bigint;
        fabricIndex: number;
    }>;
    /** Discover commissionable devices */
    handleDiscovery({ findBy }: DiscoveryRequest): Promise<DiscoveryResponse>;
    getNodeIpAddresses(nodeId: NodeId, preferCache?: boolean): Promise<string[]>;
    /**
     * Ping a node on all its known IP addresses.
     * @param nodeId The node ID to ping
     * @param attempts Number of ping attempts per IP (default: 1)
     * @returns A record of IP addresses to ping success status
     */
    pingNode(nodeId: NodeId, attempts?: number): Promise<NodePingResult>;
    decommissionNode(nodeId: NodeId): Promise<void>;
    openCommissioningWindow(data: OpenCommissioningWindowRequest): Promise<OpenCommissioningWindowResponse>;
    getFabrics(nodeId: NodeId): Promise<{
        fabricId: any;
        vendorId: any;
        fabricIndex: any;
        label: any;
    }[]>;
    removeFabric(nodeId: NodeId, fabricIndex: FabricIndex): Promise<OperationalCredentials.NocResponse>;
    /**
     * Set Access Control List entries on a node.
     * Writes to the ACL attribute on the AccessControl cluster (endpoint 0).
     * TODO Migrate to new Node API
     */
    setAclEntry(nodeId: NodeId, entries: AccessControlEntry[]): Promise<AttributeWriteResult[] | null>;
    /**
     * Set bindings on a specific endpoint of a node.
     * Writes to the Binding attribute on the Binding cluster.
     * TODO Migrate to new Node API
     */
    setNodeBinding(nodeId: NodeId, endpointId: EndpointNumber, bindings: BindingTarget[]): Promise<AttributeWriteResult[] | null>;
    /**
     * Check if a software update is available for a node.
     * First checks the cached updates from OTA events, then queries the DCL if not found.
     */
    checkNodeUpdate(nodeId: NodeId): Promise<MatterSoftwareVersion | null>;
    /**
     * Trigger a software update for a node.
     * @param nodeId The node to update
     * @param softwareVersion The target software version to update to
     */
    updateNode(nodeId: NodeId, softwareVersion: number): Promise<MatterSoftwareVersion | null>;
}
//# sourceMappingURL=ControllerCommandHandler.d.ts.map