/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ICriticalContainerError } from "@fluidframework/container-definitions";
import { IDisposable } from "@fluidframework/core-interfaces";
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
import { InboundSequencedContainerRuntimeMessage } from "./messageTypes.js";
/**
 * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the
 * ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.
 */
export interface IPendingMessage {
    type: "message";
    referenceSequenceNumber: number;
    content: string;
    localOpMetadata: unknown;
    opMetadata: Record<string, unknown> | undefined;
    sequenceNumber?: number;
}
export interface IPendingLocalState {
    /**
     * list of pending states, including ops and batch information
     */
    pendingStates: IPendingMessage[];
}
export interface IPendingBatchMessage {
    content: string;
    localOpMetadata: unknown;
    opMetadata: Record<string, unknown> | undefined;
}
export interface IRuntimeStateHandler {
    connected(): boolean;
    clientId(): string | undefined;
    close(error?: ICriticalContainerError): void;
    applyStashedOp(content: string): Promise<unknown>;
    reSubmit(message: IPendingBatchMessage): void;
    reSubmitBatch(batch: IPendingBatchMessage[]): void;
    isActiveConnection: () => boolean;
    isAttached: () => boolean;
}
/**
 * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
 * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed
 * batches along with the messages.
 * When the Container reconnects, it replays the pending states, which includes manual flushing
 * of messages and triggering resubmission of unacked ops.
 *
 * It verifies that all the ops are acked, are received in the right order and batch information is correct.
 */
export declare class PendingStateManager implements IDisposable {
    private readonly stateHandler;
    private readonly logger;
    private readonly pendingMessages;
    private readonly initialMessages;
    /**
     * Sequenced local ops that are saved when stashing since pending ops may depend on them
     */
    private savedOps;
    private readonly disposeOnce;
    private isProcessingBatch;
    private pendingBatchBeginMessage;
    private clientId;
    /**
     * The pending messages count. Includes `pendingMessages` and `initialMessages` to keep in sync with
     * 'hasPendingMessages'.
     */
    get pendingMessagesCount(): number;
    /**
     * The minimumPendingMessageSequenceNumber is the minimum of the first pending message and the first initial message.
     *
     * We need this so that we can properly keep local data and maintain the correct sequence window.
     */
    get minimumPendingMessageSequenceNumber(): number | undefined;
    /**
     * Called to check if there are any pending messages in the pending message queue.
     * @returns A boolean indicating whether there are messages or not.
     */
    hasPendingMessages(): boolean;
    getLocalState(snapshotSequenceNumber?: number): IPendingLocalState;
    constructor(stateHandler: IRuntimeStateHandler, initialLocalState: IPendingLocalState | undefined, logger: ITelemetryLoggerExt | undefined);
    get disposed(): boolean;
    readonly dispose: () => void;
    /**
     * Called when a message is submitted locally. Adds the message and the associated details to the pending state
     * queue.
     * @param type - The container message type.
     * @param content - The message content.
     * @param localOpMetadata - The local metadata associated with the message.
     */
    onSubmitMessage(content: string, referenceSequenceNumber: number, localOpMetadata: unknown, opMetadata: Record<string, unknown> | undefined): void;
    /**
     * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted
     * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.
     */
    applyStashedOpsAt(seqNum?: number): Promise<void>;
    /**
     * Processes a local message once its ack'd by the server. It verifies that there was no data corruption and that
     * the batch information was preserved for batch messages.
     * @param message - The message that got ack'd and needs to be processed.
     */
    processPendingLocalMessage(message: InboundSequencedContainerRuntimeMessage): unknown;
    /**
     * This message could be the first message in batch. If so, set batch state marking the beginning of a batch.
     * @param message - The message that is being processed.
     */
    private maybeProcessBatchBegin;
    /**
     * This message could be the last message in batch. If so, clear batch state since the batch is complete.
     * @param message - The message that is being processed.
     */
    private maybeProcessBatchEnd;
    /**
     * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending
     * states in its queue. This includes triggering resubmission of unacked ops.
     * ! Note: successfully resubmitting an op that has been successfully sequenced is not possible due to checks in the ConnectionStateHandler (Loader layer)
     */
    replayPendingStates(): void;
}
//# sourceMappingURL=pendingStateManager.d.ts.map