/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { InternalError, Observable } from "@matter/general";
import { BdxStatusCode } from "@matter/types";
import { BdxError } from "../BdxError.js";
class Flow {
  #transferParameters;
  #messenger;
  #isClosed = false;
  #blockCounter = -1;
  #bytesLeft;
  #finalBlockCounter;
  progressInfo = Observable();
  progressFinished = Observable();
  progressCancelled = Observable();
  #dataLength;
  #transferredBytes = 0;
  constructor(messenger, transferParameters) {
    this.#messenger = messenger;
    this.#transferParameters = transferParameters;
    this.#bytesLeft = transferParameters.dataLength;
    this.#dataLength = transferParameters.dataLength;
  }
  set dataLength(value) {
    this.#dataLength = value;
  }
  get dataLength() {
    return this.#dataLength;
  }
  set transferredBytes(value) {
    this.#transferredBytes = value;
  }
  get transferredBytes() {
    return this.#transferredBytes;
  }
  get transferParameters() {
    return this.#transferParameters;
  }
  get isClosed() {
    return this.#isClosed;
  }
  get messenger() {
    return this.#messenger;
  }
  get bytesLeft() {
    return this.#bytesLeft;
  }
  set bytesLeft(value) {
    this.#bytesLeft = value;
  }
  set finalBlockCounter(blockCounter) {
    if (this.#finalBlockCounter !== void 0) {
      throw new InternalError("Transfer already finalized. finalizeTransfer() should only be called once.");
    }
    this.#finalBlockCounter = blockCounter;
  }
  get finalBlockCounter() {
    if (this.#finalBlockCounter === void 0) {
      throw new InternalError("Transfer not finalized. Call finalizeTransfer() after completing the transfer.");
    }
    return this.#finalBlockCounter;
  }
  /** Determines the next message counter to use for the next message, also handles wrapping around at 2^32. */
  get nextMessageCounter() {
    this.#blockCounter = (this.#blockCounter + 1) % 4294967296;
    return this.#blockCounter;
  }
  /** Utility function to check if a block counter is valid */
  validateCounter(messageBlockCounter, expectedCounter = this.nextMessageCounter) {
    if (messageBlockCounter !== expectedCounter) {
      throw new BdxError(
        `Received Block with unexpected block counter: ${messageBlockCounter}, expected: ${expectedCounter}`,
        BdxStatusCode.BadBlockCounter
      );
    }
    return messageBlockCounter;
  }
  async close(_error) {
    this.#isClosed = true;
  }
  /**
   * Main logic method to execute the flow.
   * The promise resolves when the flow is complete, or rejects on any error or unexpected conditions.
   */
  async processTransfer() {
    await this.initTransfer();
    this.progressInfo.emit(0, this.dataLength);
    try {
      while (!this.isClosed) {
        if (await this.transferNextChunk()) {
          break;
        }
        this.progressInfo.emit(this.transferredBytes, this.dataLength);
      }
      this.progressInfo.emit(this.transferredBytes, this.dataLength);
      if (this.isClosed) {
        this.progressCancelled.emit();
      } else {
        await this.finalizeTransfer();
        this.progressFinished.emit(this.transferredBytes);
      }
    } catch (error) {
      this.progressCancelled.emit();
      throw error;
    }
  }
}
((Flow2) => {
  let DriverMode;
  ((DriverMode2) => {
    DriverMode2["SenderDrive"] = "senderDrive";
    DriverMode2["ReceiverDrive"] = "receiverDrive";
  })(DriverMode = Flow2.DriverMode || (Flow2.DriverMode = {}));
})(Flow || (Flow = {}));
export {
  Flow
};
//# sourceMappingURL=Flow.js.map
