/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Message } from "#codec/MessageCodec.js";
import { NetworkProfile } from "#peer/NetworkProfile.js";
import { Session } from "#session/Session.js";
import { SessionParameters } from "#session/SessionParameters.js";
import { AsyncObservableValue, Bytes, Duration, Lifetime, ServerAddressUdp } from "@matter/general";
import { NodeId } from "@matter/types";
import { MessageChannel } from "./MessageChannel.js";
export type ExchangeLogContext = Record<string, unknown>;
export interface ExchangeSendOptions {
    /**
     * The response to this send should be an ack only and no StatusResponse or such. If a StatusResponse is returned
     * then this is handled as error.
     */
    expectAckOnly?: boolean;
    /**
     * If the message is part of a multiple message interaction, this flag indicates that it is not allowed
     * to establish a new exchange
     */
    multipleMessageInteraction?: boolean;
    /**
     * Defined an expected processing time by the responder for the message. This is used to calculate the final
     * timeout for responses together with the normal retransmission logic when MRP is used.
     */
    expectedProcessingTime?: Duration;
    /** Allows to specify if the send message requires to be acknowledged by the receiver or not. */
    requiresAck?: boolean;
    /**
     * Disables the MRP logic which means that no retransmissions are done and receiving an ack is not awaited.
     */
    disableMrpLogic?: boolean;
    /** Additional context information for logging to be included at the beginning of the Message log. */
    logContext?: ExchangeLogContext;
    /** Aborts sending; does not throw */
    abort?: AbortSignal;
    /** Number of MRP retries to attempt (default: MRP.MAX_TRANSMISSIONS) */
    maxRetransmissions?: number;
    /** Maximum MRP retransmission time (default: unlimited) */
    maxRetransmissionTime?: Duration;
    /** Initial MRP retransmission time (default: calculated as by Matter specification) */
    initialRetransmissionTime?: Duration;
}
export interface ExchangeReceiveOptions {
    /** Aborts sending; does not throw */
    abort?: AbortSignal;
    timeout?: Duration;
    /**
     * Defined an expected processing time by the responder for the message. This is used to calculate the final
     * timeout for responses together with the normal retransmission logic when MRP is used.
     */
    expectedProcessingTime?: Duration;
}
/**
 * Message size overhead of a Matter message:
 * 26 (Matter Message Header) + 12 (Matter Payload Header) taken from https://github.com/project-chip/connectedhomeip/blob/2d97cda23024e72f36216900ca667bf1a0d9499f/src/system/SystemConfig.h#L327
 * 16 byte MIC is then also needed to be excluded from the max payload size
 * Secure Extensions and Message Extensions need to be handled by exchange additionally!
 */
export declare const MATTER_MESSAGE_OVERHEAD: number;
/**
 * Interfaces {@link MessageExchange} with other components.
 */
export interface MessageExchangeContext {
    session: Session;
    localSessionParameters: SessionParameters;
    peerLost(exchange: MessageExchange, cause: Error): Promise<void>;
    /** @deprecated */
    retry(number: number): void;
}
/**
 * A Matter "message exchange" is a sequence of messages associated with a single interaction.
 *
 * TODO - rewrite main send retransmission loop using sleeps instead of timers
 * TODO - track dangling promises (annotated with TODO)
 * TODO - replace throws with logging for some errors triggered by peer
 */
export declare class MessageExchange {
    #private;
    static fromInitialMessage(context: MessageExchangeContext, initialMessage: Message, options?: MessageExchange.Options): MessageExchange;
    static initiate(context: MessageExchangeContext, exchangeId: number, protocolId: number, options?: MessageExchange.Options): MessageExchange;
    constructor(config: MessageExchange.Config);
    get context(): MessageExchangeContext;
    get isInitiator(): boolean;
    /** Emits when the exchange is actually closed. This happens after all Retries and Communication are done. */
    get closed(): AsyncObservableValue<[any, ...any[]]>;
    get considerClosed(): any;
    /**
     * Emit when the exchange is closing, but not yet closed. We only wait for acks and retries to happen, but the
     * actual interaction logic is already done.
     */
    get closing(): AsyncObservableValue<[any, ...any[]]>;
    get id(): number;
    get idStr(): string;
    get session(): Session;
    /** Number of retransmissions of the current outstanding message (resets on ack or new send). */
    get retransmissionCount(): number;
    get channel(): MessageChannel;
    /**
     * Max Payload size of the exchange which bases on the maximum payload size of the channel reduced by Matter
     * protocol overhead.
     */
    get maxPayloadSize(): number;
    join(...name: unknown[]): Lifetime;
    onMessageReceived(message: Message, duplicate?: boolean): Promise<void>;
    send(messageType: number, payload: Bytes, options?: ExchangeSendOptions): Promise<void>;
    nextMessage(options?: ExchangeReceiveOptions): Promise<Message>;
    sendStandaloneAckForMessage(message: Message): Promise<void>;
    [Symbol.asyncDispose](): Promise<void>;
    destroy(): Promise<void>;
    startTimedInteraction(timeout: Duration): void;
    clearTimedInteraction(): void;
    hasTimedInteraction(): boolean;
    hasActiveTimedInteraction(): boolean;
    hasExpiredTimedInteraction(): boolean;
    /**
     * Closes the exchange.
     *
     * If cause is defined, the exchange is closed immediately, even if there are still messages to send.  Further
     * attempts at communicating via the exchange will throw this error.
     *
     * If cause is undefined, the exchange is closed only after all messages have been sent.
     */
    close(cause?: Error): Promise<void>;
    get via(): string;
    /**
     * Expose some diagnostics for logging.
     * For simply one message exchanges without retransmissions nothing will be exposed
     */
    get diagnostics(): string;
}
export declare namespace MessageExchange {
    interface Options {
        /**
         * Invoked when a message transmits
         */
        onSend?: SendNotifier;
        /**
         * Invoked upon message receipt.
         */
        onReceive?: ReceiveNotifier;
        /**
         * Network Profile used
         */
        network?: NetworkProfile;
        /**
         * Optional address override for this exchange.  When set, messages are sent to this address
         * instead of the session's default peer address.
         */
        addressOverride?: ServerAddressUdp;
    }
    interface Config extends Options {
        context: MessageExchangeContext;
        isInitiator: boolean;
        peerSessionId: number;
        nodeId?: NodeId;
        peerNodeId?: NodeId;
        exchangeId: number;
        protocolId: number;
    }
    /**
     * Callback invoked by exchange before message transmission.
     */
    type SendNotifier = (message: Message, retransmission: number) => void;
    /**
     * Callback invoked by exchange after message receipt.
     */
    type ReceiveNotifier = (message: Message, duplicate: boolean) => void;
}
//# sourceMappingURL=MessageExchange.d.ts.map