import { type CCEncodingContext, type CommandClass } from "@zwave-js/cc";
import { type CommandClassInfo, type CommandClasses, type SecurityManagers } from "@zwave-js/core";
import { type KeyPair } from "@zwave-js/shared/bindings";
import type { CCIdToCapabilities } from "./CCSpecificCapabilities.js";
import type { MockController } from "./MockController.js";
import { type MockEndpointCapabilities, type MockNodeCapabilities, type PartialCCCapabilities } from "./MockNodeCapabilities.js";
import { type LazyMockZWaveFrame, type MockZWaveAckFrame, type MockZWaveFrame, type MockZWaveRequestFrame } from "./MockZWaveFrame.js";
export interface MockNodeOptions {
    id: number;
    controller: MockController;
    capabilities?: Partial<MockNodeCapabilities> & {
        /** The CCs implemented by the root device of this node */
        commandClasses?: PartialCCCapabilities[];
        /** Additional, consecutive endpoints. The first one defined will be available at index 1. */
        endpoints?: (Partial<MockEndpointCapabilities> & {
            commandClasses?: PartialCCCapabilities[];
        })[];
    };
}
export interface MockEndpointOptions {
    index: number;
    node: MockNode;
    capabilities?: Partial<MockEndpointCapabilities> & {
        /** The CCs implemented by this endpoint */
        commandClasses?: PartialCCCapabilities[];
    };
}
export type NodePendingInclusion = Omit<MockNodeOptions, "controller"> & {
    /** Optional callback that is called when the node is created during inclusion */
    setup?: (node: MockNode) => void;
};
export declare class MockEndpoint {
    constructor(options: MockEndpointOptions);
    readonly index: number;
    readonly node: MockNode;
    readonly capabilities: MockEndpointCapabilities;
    readonly implementedCCs: Map<CommandClasses, CommandClassInfo>;
    /** Adds information about a CC to this mock endpoint */
    addCC(cc: CommandClasses, info: Partial<CommandClassInfo>): void;
    /** Removes information about a CC from this mock node */
    removeCC(cc: CommandClasses): void;
}
/** A mock node that can be used to test the driver as if it were speaking to an actual network */
export declare class MockNode {
    static create(options: MockNodeOptions): Promise<MockNode>;
    private constructor();
    private _options;
    readonly id: number;
    readonly controller: MockController;
    readonly capabilities: MockNodeCapabilities;
    securityManagers: SecurityManagers;
    ecdhKeyPair: KeyPair;
    get dsk(): string;
    get s2Pin(): string;
    private setupSecurity;
    encodingContext: CCEncodingContext;
    private behaviors;
    readonly implementedCCs: Map<CommandClasses, CommandClassInfo>;
    readonly endpoints: Map<number, MockEndpoint>;
    /** Can be used by behaviors to store controller related state */
    readonly state: Map<string, unknown>;
    /** Controls whether the node automatically ACKs CCs from the controller before handling them */
    autoAckControllerFrames: boolean;
    private expectedControllerFrames;
    /** Records the frames received from the controller to perform assertions on them */
    private receivedControllerFrames;
    /** Records the frames sent to the controller to perform assertions on them */
    private sentControllerFrames;
    /**
     * Waits until the controller sends a frame matching the given predicate or a timeout has elapsed.
     *
     * @param predicate A predicate function to test incoming frames
     * @param options Optional configuration
     * @param options.timeout The number of milliseconds to wait. If the timeout elapses, the returned promise will be rejected. Default: 5000ms
     * @param options.preventDefault If true, the default behavior will not be executed after the expectation is fulfilled. Default: false
     */
    expectControllerFrame<T extends MockZWaveFrame = MockZWaveFrame>(predicate: (msg: MockZWaveFrame) => msg is T, options?: {
        timeout?: number;
        preventDefault?: boolean;
        errorMessage?: string;
    }): Promise<T>;
    /**
     * Waits until the controller sends an ACK frame or a timeout has elapsed.
     *
     * @param timeout The number of milliseconds to wait. If the timeout elapses, the returned promise will be rejected
     */
    expectControllerACK(timeout: number, errorMessage?: string): Promise<MockZWaveAckFrame>;
    /**
     * Sends a {@link MockZWaveFrame} to the {@link MockController}
     */
    sendToController(frame: LazyMockZWaveFrame): Promise<MockZWaveAckFrame | undefined>;
    /** Gets called when a {@link MockZWaveFrame} is received from the {@link MockController} */
    onControllerFrame(frame: MockZWaveFrame): Promise<void>;
    /**
     * Sends an ACK frame to the {@link MockController}
     */
    ackControllerRequestFrame(frame?: MockZWaveRequestFrame): Promise<void>;
    /**
     * Applies all response transformation hooks to a mock response and sends the
     * final result to the controller.
     */
    sendResponse(receivedCC: CommandClass, response: MockNodeResponse, frame?: MockZWaveRequestFrame): Promise<void>;
    /** Adds information about a CC to this mock node */
    addCC(cc: CommandClasses, info: Partial<CommandClassInfo>): void;
    /** Removes information about a CC from this mock node */
    removeCC(cc: CommandClasses): void;
    defineBehavior(...behaviors: MockNodeBehavior[]): void;
    /** Asserts that a frame matching the given predicate was received from the controller */
    assertReceivedControllerFrame(predicate: (frame: MockZWaveFrame) => boolean, options?: {
        noMatch?: boolean;
        errorMessage?: string;
    }): void;
    /** Forgets all recorded frames received from the controller */
    clearReceivedControllerFrames(): void;
    /** Asserts that a frame matching the given predicate was sent to the controller */
    assertSentControllerFrame(predicate: (frame: MockZWaveFrame) => boolean, options?: {
        noMatch?: boolean;
        errorMessage?: string;
    }): void;
    /** Forgets all recorded frames sent to the controller */
    clearSentControllerFrames(): void;
    getCCCapabilities<T extends CommandClasses>(ccId: T, endpointIndex?: number): Partial<CCIdToCapabilities<T>> | undefined;
}
/** What the mock node should do after receiving a controller frame */
export type MockNodeResponse = {
    action: "sendCC";
    cc: CommandClass;
    ackRequested?: boolean;
} | {
    action: "ack";
} | {
    action: "stop";
} | {
    action: "ok";
    /** If set, indicates how long the action will take to complete */
    durationMs?: number;
} | {
    action: "fail";
};
export interface MockNodeBehavior {
    /** Gets called before the `handleCC` handlers and can transform an incoming `CommandClass` into another */
    transformIncomingCC?: (controller: MockController, self: MockNode, cc: CommandClass) => Promise<CommandClass> | CommandClass;
    /** Gets called when a CC from the controller is received. Returns an action to be performed in response, or `undefined` if there is nothing to do. */
    handleCC?: (controller: MockController, self: MockNode, receivedCC: CommandClass) => Promise<MockNodeResponse | undefined> | MockNodeResponse | undefined;
    /** Gets called after the `onControllerFrame` handlers and can transform one `MockNodeResponse` into another */
    transformResponse?: (controller: MockController, self: MockNode, receivedCC: CommandClass, response: MockNodeResponse) => Promise<MockNodeResponse> | MockNodeResponse;
}
//# sourceMappingURL=MockNode.d.ts.map