/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Behavior } from "#behavior/Behavior.js";
import { Events as BaseEvents } from "#behavior/Events.js";
import { Endpoint } from "#endpoint/Endpoint.js";
import { AsyncObservable, AsyncObservableValue, Bytes, Duration, Observable, Observer, Timestamp } from "@matter/general";
import { PeerAddress, type FabricIcd } from "@matter/protocol";
import { SubjectId, VendorId } from "@matter/types";
import { IcdManagement } from "@matter/types/clusters/icd-management";
/**
 * Controller-side client for ICD (Intermittently Connected Device) Check-In support.
 *
 * Auto-installed on a {@link ClientNode} whose peer exposes the IcdManagement cluster. Registration — automatic for a
 * LIT-operating peer, or explicit via {@link register} — requires an established subscription so the decision runs on a
 * fresh operating mode rather than a stale cached one. The behavior tracks peer wakefulness to hold interactions for a
 * sleeping ICD.
 *
 * @see {@link MatterSpecification.v16.Core} § 9.15.1, § 9.16
 */
export declare class IcdClient extends Behavior {
    #private;
    internal: IcdClient.Internal;
    readonly state: IcdClient.State;
    readonly events: IcdClient.Events;
    static readonly early = true;
    static readonly id = "icd";
    get isRegistered(): boolean;
    /** Whether the peer is LIT-capable (LongIdleTimeSupport feature and specification version >= 1.4.0). */
    get peerSupportsLit(): boolean;
    /**
     * Whether the peer is currently awake. A non-LIT or not-yet-fed peer has nothing to await and reads true.
     */
    get awake(): any;
    /**
     * Deadline by which the next Check-In from a registered LIT peer is expected, or undefined when no Check-In is
     * scheduled (no fed peer / not registered / not LIT). Derived from the fed peer's wakefulness availability window.
     */
    get nextExpectedCheckin(): Timestamp | undefined;
    initialize(): void;
    /**
     * Register this controller as a Check-In client on the peer.
     *
     * Installs a shared {@link IcdManagement.RegisterClientRequest.key} on the peer so it can send us encrypted
     * Check-In messages, records the rolling-counter baseline in {@link IcdClient.State}, and arms the controller-side Check-In
     * receive path on the fabric.
     *
     * @throws {ImplementationError} if the peer is not online (registration reads from and writes to the peer), or its
     *   IcdManagement cluster lacks the Check-In Protocol feature.
     * @throws {IcdMultiAdminError} if the peer has more than one administrator from other vendors and
     *   `allowMultiAdmin` is not set — see {@link IcdMultiAdminError.assertSingleAdmin}.
     */
    register(options?: {
        monitoredSubject?: SubjectId;
        clientType?: IcdManagement.ClientType;
        allowMultiAdmin?: boolean;
        ignoredVendors?: VendorId[];
    }): Promise<void>;
    /**
     * Remove this controller's Check-In registration from the peer and tear down the local receive path.
     *
     * Best-effort on the peer: local state is cleared even if the peer {@link IcdManagement.unregisterClient} fails (it
     * may be unreachable). A no-op when not registered.
     */
    unregister(): Promise<void>;
    /**
     * Locally drop this controller's Check-In registration without contacting the peer.
     *
     * Escape hatch for an unreachable registered LIT peer: {@link unregister} round-trips to the peer, so it parks on
     * the same wakefulness deadlock this clears. Dropping the fed peer removes its wakefulness, so subsequent
     * interactions no longer hold — a later subscribe can re-establish and re-register. The peer keeps a stale
     * registration for us until it prunes it (or a fresh {@link register} mints a new key). A no-op when not registered.
     */
    forget(): Promise<void>;
    /**
     * Ask the peer to remain in Active mode for at least `duration` and return the duration it actually promised.
     *
     * @see {@link MatterSpecification.v16.Core} § 9.16.7.4
     */
    stayActive(duration: Duration): Promise<Duration>;
    /**
     * Wait for an in-flight key refresh to finish on teardown — aborting between the peer re-key and our state write
     * would leave the controller and peer with mismatched keys.
     */
    [Symbol.asyncDispose](): Promise<void>;
}
export declare namespace IcdClient {
    /** Minimum device Matter specification version (BasicInformation, encoded 0xMMmmpprr) for trustworthy LIT behavior. */
    const MIN_LIT_SPECIFICATION_VERSION = 17039360;
    /**
     * Whether a peer is LIT-capable: advertises LongIdleTimeSupport AND reports Matter specification version >= 1.4.0.
     * Devices below 1.4.0 (or not reporting a version) are treated as non-LIT regardless of the feature flag.
     */
    function litSupported(endpoint: Endpoint): boolean;
    class Internal {
        /** Retained across re-registrations so the protocol RX path stays armed without creating a second closure. */
        checkInHandler?: FabricIcd.CheckInHandler;
        /** In-flight key refresh; tracked so a second refreshNeeded Check-In can't overlap it and teardown can await it. */
        keyRefresh?: Promise<void>;
        /** In-flight LIT auto-registration; tracked so overlapping triggers can't double-register and teardown can await it. */
        autoRegister?: Promise<void>;
        /** Set when a trigger arrives while {@link autoRegister} is in flight, so it re-evaluates on completion. */
        autoRegisterPending?: boolean;
        /** Address of the peer fed to {@link FabricIcd}; lets decommission drop it after peerAddress is already gone. */
        fedPeer?: PeerAddress;
        /** The fed peer's wakefulness `available` observable we currently mirror; recreated on every feed. */
        availableSource?: AsyncObservableValue<[boolean]>;
        /** Listener mirroring {@link availableSource} into {@link IcdClient.State.available}; removed on drop and before re-feed. */
        availableListener?: Observer<[boolean]>;
        /** The fed peer's wakefulness `checkInMissed` observable we currently mirror; recreated on every feed. */
        checkInMissedSource?: AsyncObservable<[]>;
        /** Listener mirroring {@link checkInMissedSource} into {@link IcdClient.Events.checkInMissed}; removed on drop and before re-feed. */
        checkInMissedListener?: Observer<[]>;
    }
    class State {
        /**
         * Shared secret installed on the peer at registration, used to verify Check-In message ICD counters.
         */
        key?: Bytes;
        /**
         * ICD counter value the peer reported at registration; Check-In counters are validated relative to this.
         */
        counterStart?: number;
        /**
         * Offset of the most recently observed Check-In counter from {@link counterStart}.
         */
        lastOffset?: number;
        /**
         * Subject the peer monitors on our behalf (the node ID notified on Check-In).
         */
        monitoredSubject?: SubjectId;
        /**
         * Client type registered with the peer (permanent or ephemeral).
         */
        clientType?: IcdManagement.ClientType;
        /**
         * Whether this controller is currently registered as a Check-In client on the peer.
         */
        registered: boolean;
        /**
         * Time of the most recently received Check-In from the peer.
         */
        lastCheckInReceivedAt?: Timestamp;
        /**
         * Whether the peer is reachable (within its expected Check-In window). Non-LIT peers are always available.
         */
        available: boolean;
    }
    class Events extends BaseEvents {
        registered: Observable<any[], void>;
        unregistered: Observable<any[], void>;
        checkedIn: Observable<[checkIn: {
            counter: number;
            activeModeThreshold: number;
        }], void>;
        keyRefreshed: Observable<any[], void>;
        available$Changed: Observable<[value: boolean, oldValue: boolean], void>;
        /** Emits when a registered LIT peer misses its expected Check-In (its availability window lapsed). */
        checkInMissed: Observable<any[], void>;
    }
}
//# sourceMappingURL=IcdClient.d.ts.map