/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Behavior } from "#behavior/Behavior.js";
import { OtaAnnouncements } from "#behavior/system/software-update/OtaAnnouncements.js";
import { Endpoint } from "#endpoint/Endpoint.js";
import type { ClientNode } from "#node/ClientNode.js";
import { Bytes, Duration, EventEmitter, Observable, ObserverGroup, Timer, Timestamp } from "@matter/general";
import { DclOtaUpdateService, FileDesignator, OtaUpdateSource, PeerAddress, PeerAddressMap } from "@matter/protocol";
import { VendorId } from "@matter/types";
import { OtaSoftwareUpdateProvider } from "@matter/types/clusters/ota-software-update-provider";
interface UpdateConsent {
    vendorId: VendorId;
    productId: number;
    targetSoftwareVersion: number;
    peerAddress: PeerAddress;
}
interface UpdateQueueEntry extends UpdateConsent {
    endpoint: Endpoint;
    lastProgressUpdateTime?: Timestamp;
    lastProgressStatus?: OtaUpdateStatus;
}
export interface OtaUpdateAvailableDetails {
    newSoftwareVersion: number;
    newSoftwareVersionString: string;
    fileDesignator: FileDesignator;
    httpsUri?: string;
    consentRequired: boolean;
    metadataForRequestor?: Bytes;
}
export declare enum OtaUpdateStatus {
    Unknown = 0,
    WaitForConsent = 1,
    Querying = 2,
    Downloading = 3,
    WaitForApply = 4,
    Applying = 5,
    Done = 6,
    Cancelled = 7
}
export interface SoftwareUpdateInfo {
    /** VendorId of the updated device */
    vendorId: VendorId;
    /** ProductId of the updated device */
    productId: number;
    /** Software version of the updated device */
    softwareVersion: number;
    /** Software Version String of the updated device */
    softwareVersionString: string;
    /** ReleaseNotesUrl for the update */
    releaseNotesUrl?: string;
    /** SpecificationVersion of the updated device */
    specificationVersion?: number;
    /** Source of the update returned, whether it is a local file, downloaded from test or production DCL */
    source: OtaUpdateSource;
}
export interface PendingUpdateInfo {
    peerAddress: PeerAddress;
    vendorId: VendorId;
    productId: number;
    targetSoftwareVersion: number;
    /**
     * - `"queued"` — waiting for its turn; no announcement has been sent yet.
     * - `"in-progress"` — the OTA provider has been announced to the node and we are waiting for it to complete.
     * - `"stalled"` — no progress update received for 15 minutes. The entry will be automatically reset and retried.
     */
    status: "queued" | "in-progress" | "stalled";
    lastProgressStatus?: OtaUpdateStatus;
    lastProgressUpdateTime?: Timestamp;
}
/**
 * The Software Update Manager is the instance to bridge between the central OTA store and DCL service and manage the
 * updates for all peers of a node. It gets installed on the endpoint where the OtaSoftwareUpdateProvider behavior is
 * installed. It uses the generic DclOtaUpdateService, which exists globally, to request and get new updates.
 *
 * The following state allows configuring the behavior:
 * * {@link allowTestOtaImages}: When set to true, we also query the Test DCL additionally to the production DCL for update
 *     and use this when a newer version is found. Default is false
 *
 * * {@link updateCheckInterval}: By default, we check the DCL for updates every 24h. This state value allows adjusting this.
 *
 * * {@link announceAsDefaultProvider}: By default, we announce ourselves as a default update provider to all nodes in the fabric.
 *     Set to "false" if this is not wanted and updates are only pushed on availability
 */
export declare class SoftwareUpdateManager extends Behavior {
    #private;
    static readonly id = "softwareupdates";
    readonly state: SoftwareUpdateManager.State;
    internal: SoftwareUpdateManager.Internal;
    readonly events: SoftwareUpdateManager.Events;
    initialize(): Promise<void>;
    get storage(): import("@matter/protocol").ScopedStorage;
    /**
     * Returns a snapshot of the current update queue for introspection.
     */
    get queuedUpdates(): PendingUpdateInfo[];
    /**
     * Used to determine if an update is existing in our storage for a peer with a certain software version.
     *
     * It uses the already checked details and does not check again on-demand. It considers consents already given,
     * but validates the peer data.
     */
    updateExistsFor(peerAddress: PeerAddress, { softwareVersion, vendorId, productId, requestorCanConsent }: OtaSoftwareUpdateProvider.QueryImageRequest): Promise<OtaUpdateAvailableDetails | undefined>;
    /**
     * Checks all nodes, or optionally a defined one, for available updates from the DCL OTA Update Service.
     *
     * Returns a list of peers for which updates are available along with the collected update info.
     *
     * If `includeStoredUpdates` is set to true available and known local update will be returned without checking the
     * DCL again.
     */
    queryUpdates(options?: {
        peerToCheck?: ClientNode;
        includeStoredUpdates?: boolean;
    }): Promise<{
        peerAddress: PeerAddress;
        info: SoftwareUpdateInfo;
    }[]>;
    /**
     * Notify the application that consent is needed for the given update on the given peer
     */
    protected requestConsentForUpdate(peerAddress: PeerAddress, updateDetails: SoftwareUpdateInfo): void;
    /**
     * Forces an OTA update for a specific node identified by its peer address, vendor ID, product ID,
     * and target software version. This method will override any ongoing updates by explicitly adding an update
     * consent for the specified node and processing the update immediately if applicable.
     * This can be used when an exact timing of the update is needed. When the update can be executed in a delayed/queued
     * manner, please use `addUpdateConsent()`.
     */
    forceUpdate(peerAddress: PeerAddress, vendorId: VendorId, productId: number, targetSoftwareVersion: number): Promise<void>;
    /**
     * Adds or updates a consent for a given peer address, vendor ID, product ID, and target software version.
     * Filters out existing consents for the given peer address and replaces them with the new one.
     * If the node associated with the peer address is applicable for an update, it schedules the update to happen with
     * the next queue slot, so potentially delayed.
     * This can be used when the update can be executed in a delayed/queued manner and it does not matter exactly when.
     */
    addUpdateConsent(peerAddress: PeerAddress, vendorId: VendorId, productId: number, targetSoftwareVersion: number): Promise<boolean>;
    /**
     * Checks if consent exists for the given peer address and optionally for a specific target software version.
     */
    hasConsent(peerAddress: PeerAddress, targetSoftwareVersion?: number): boolean;
    /**
     * Checks for consent and removes it if present, also cancels if in progress. Use this to remove a formerly given
     * consent.
     */
    removeConsent(peerAddress: PeerAddress, targetSoftwareVersion?: number): Promise<void>;
    /**
     * Suppress the next startUp event from the given peer on the given session.
     * Called by OtaSoftwareUpdateProviderServer when a queryImage is detected as a post-reboot query
     * so the startUp event that follows is not treated as a new failure-after-apply.
     */
    suppressNextStartUp(peerAddress: PeerAddress, sessionId: number): void;
    /**
     * Handles the status change of an OTA update for a given peer device.
     *
     * This method processes OTA update status notifications received from a specified device.
     * Based on the status, it updates the internal state of the update queue, logs relevant
     * messages, and triggers the necessary events.
     */
    onOtaStatusChange(peerAddress: PeerAddress, status: OtaUpdateStatus, toVersion?: number): void;
    [Symbol.asyncDispose](): Promise<void>;
}
export declare namespace SoftwareUpdateManager {
    class State {
        /** Set this to true to also allow updates from the Test DCL */
        allowTestOtaImages: boolean;
        /** Default Update check Interval */
        updateCheckInterval: Duration;
        /** Announce this controller as Update provider to all nodes */
        announceAsDefaultProvider: boolean;
        /** Interval to Announces this controller as Update provider. Must not be lower than 24h! */
        announcementInterval: Duration;
    }
    class Internal {
        /** Use this to pre-initialize consent to allow nodes to update automatically. The content will not be persisted! */
        consents: UpdateConsent[];
        otaService: DclOtaUpdateService;
        checkForUpdateTimer: Timer;
        updateQueue: UpdateQueueEntry[];
        updateQueueTimer?: Timer;
        announcements?: OtaAnnouncements;
        versionUpdateObservers: ObserverGroup;
        knownUpdates: PeerAddressMap<SoftwareUpdateInfo>;
        /**
         * Peer → session ID on which the reboot-triggering queryImage was received.
         *
         * Intentionally ephemeral (not persisted): the suppress window is sub-second — between the
         * queryImage response and the subsequent startUp event that follows on the same session.
         * Entries are consumed immediately when the matching startUp fires in #onSoftwareVersionChanged,
         * or cleaned up in #cancelUpdate when the peer is permanently removed from tracking.
         */
        pendingStartUpSuppress: PeerAddressMap<number>;
        closed: boolean;
    }
    class Events extends EventEmitter {
        /** Emitted when an update is available for a Peer and there is no consent stored and contains update details */
        updateAvailable: Observable<[peer: PeerAddress, updateDetails: SoftwareUpdateInfo], void>;
        /** Emitted when an update for a Peer is finished */
        updateDone: Observable<[peer: PeerAddress], void>;
        /** Emitted when an update for a Peer has failed or was cancelled */
        updateFailed: Observable<[peer: PeerAddress], void>;
        announceAsDefaultProvider$Changed: Observable<[announceAsDefaultProvider: boolean], void>;
        announcementInterval$Changed: Observable<[announcementInterval: Duration], void>;
    }
}
export {};
//# sourceMappingURL=SoftwareUpdateManager.d.ts.map