/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Construction, InternalError, asyncNew } from "#general";
const MAX_COUNTER_VALUE_32BIT = 4294967294;
const ROLLOVER_INFO_DIFFERENCE = 1e3;
var MessageCounterTypes = /* @__PURE__ */ ((MessageCounterTypes2) => {
  MessageCounterTypes2[MessageCounterTypes2["GlobalUnencrypted"] = 0] = "GlobalUnencrypted";
  MessageCounterTypes2[MessageCounterTypes2["GlobalEncryptedData"] = 1] = "GlobalEncryptedData";
  MessageCounterTypes2[MessageCounterTypes2["GlobalEncryptedControl"] = 2] = "GlobalEncryptedControl";
  MessageCounterTypes2[MessageCounterTypes2["SecureSession"] = 3] = "SecureSession";
  return MessageCounterTypes2;
})(MessageCounterTypes || {});
class MessageCounter {
  /**
   * Creates a new message counter with a random start value. If a aboutToRolloverCallback is provided this
   * counter is not allowed to rollover and the callback is called before a rollover would happen. Optionally provide
   * a number of messages before the rollover callback is called (Default 1000).
   */
  constructor(crypto, onRollover, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
    this.onRollover = onRollover;
    this.rolloverInfoDifference = rolloverInfoDifference;
    this.messageCounter = (crypto.randomUint32 >>> 4) + 1;
  }
  messageCounter;
  async getIncrementedCounter() {
    this.messageCounter++;
    if (this.messageCounter > MAX_COUNTER_VALUE_32BIT) {
      if (this.onRollover !== void 0) {
        this.messageCounter = 0;
      } else {
        throw new InternalError("Message counter rollover not allowed.");
      }
    } else if (this.onRollover !== void 0 && this.messageCounter === MAX_COUNTER_VALUE_32BIT - this.rolloverInfoDifference) {
      await this.onRollover();
    }
    return this.messageCounter;
  }
}
class PersistedMessageCounter extends MessageCounter {
  constructor(crypto, storageContext, storageKey, aboutToRolloverCallback, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
    super(crypto, aboutToRolloverCallback, rolloverInfoDifference);
    this.storageContext = storageContext;
    this.storageKey = storageKey;
    this.#construction = Construction(this, async () => {
      if (await storageContext.has(storageKey)) {
        this.messageCounter = await storageContext.get(storageKey);
        if (this.messageCounter < 0 || this.messageCounter > MAX_COUNTER_VALUE_32BIT) {
          throw new InternalError(`Invalid message counter value: ${this.messageCounter}`);
        }
        if (this.onRollover !== void 0 && this.messageCounter >= MAX_COUNTER_VALUE_32BIT - this.rolloverInfoDifference) {
          await this.onRollover();
        }
      }
    });
  }
  #construction;
  get construction() {
    return this.#construction;
  }
  static async create(crypto, storageContext, storageKey, aboutToRolloverCallback, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
    return asyncNew(
      PersistedMessageCounter,
      crypto,
      storageContext,
      storageKey,
      aboutToRolloverCallback,
      rolloverInfoDifference
    );
  }
  async getIncrementedCounter() {
    const counter = await super.getIncrementedCounter();
    await this.storageContext.set(this.storageKey, counter);
    return counter;
  }
}
export {
  MAX_COUNTER_VALUE_32BIT,
  MessageCounter,
  MessageCounterTypes,
  PersistedMessageCounter
};
//# sourceMappingURL=MessageCounter.js.map
