"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var LocalActorContext_exports = {};
__export(LocalActorContext_exports, {
  LocalActorContext: () => LocalActorContext,
  nextInternalId: () => nextInternalId
});
module.exports = __toCommonJS(LocalActorContext_exports);
var import_general = require("@matter/general");
var import_model = require("@matter/model");
var import_protocol = require("@matter/protocol");
var import_Contextual = require("../Contextual.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
let nextInternalId = 1;
const logger = import_general.Logger.get("LocalActorContext");
let ReadOnly;
const LocalActorContext = {
  /**
   * Operate on behalf of a local actor.  This is the context for operations on nodes initiated locally, without
   * authentication.
   *
   * {@link act} provides an {@link ActionContext} you can use to access agents for a {@link Endpoint}.
   * State changes and change events occur once {@link actor} returns.
   * It can return a promise even if the actor method does not return a promise, so manual checks are needed.
   *
   * The {@link Transaction} is destroyed with {@link act} exits so you should not keep a reference to any agents
   * beyond the lifespan of {@link actor}.
   *
   * Offline context is very permissive.  You should use carefully.
   */
  act(purpose, actor, options) {
    const interactionComplete = new import_general.AsyncObservable();
    const context = this.open(purpose, { ...options, interactionComplete });
    let result;
    try {
      result = actor(context);
    } catch (e) {
      return context.reject(e);
    }
    context.transaction.onShared(() => {
      function handleErr(err) {
        logger.warn("interactionComplete observer failed", import_general.Diagnostic.error(err));
      }
      if (interactionComplete.isObserved) {
        try {
          const result2 = interactionComplete.emit(context);
          if (import_general.MaybePromise.is(result2)) {
            return import_general.MaybePromise.then(result2, void 0, handleErr);
          }
        } catch (e) {
          handleErr(e);
        }
      }
    }, true);
    return context.resolve(result);
  },
  /**
   * Create an offline context.
   *
   * This context operates with a {@link Transaction} created via {@link Transaction.open} and the same rules
   * apply for lifecycle management using {@link Transaction.Finalization}.
   */
  open(purpose, options) {
    const id = nextInternalId;
    nextInternalId = (nextInternalId + 1) % 65535;
    const via = import_general.Diagnostic.via(`${import_protocol.Mark.LOCAL_SESSION}${purpose}#${id.toString(16)}`);
    let frame;
    let transaction;
    try {
      frame = options?.activity?.begin(via);
      transaction = import_general.Transaction.open(via, options?.lifetime ?? import_general.Lifetime.process, options?.isolation);
      if (frame) {
        transaction.onClose(frame.close.bind(frame));
      }
      const context = Object.freeze({
        ...options,
        transaction,
        activity: frame,
        interactionComplete: options?.interactionComplete,
        authorityAt(desiredAccessLevel) {
          return desiredAccessLevel === import_model.AccessLevel.View ? import_protocol.AccessControl.Authority.Granted : import_protocol.AccessControl.Authority.Unauthorized;
        },
        get [import_Contextual.Contextual.context]() {
          return this;
        },
        [Symbol.toStringTag]: "OfflineContext",
        resolve: transaction.resolve.bind(transaction),
        reject: transaction.reject.bind(transaction),
        offline: true
      });
      return context;
    } catch (e) {
      if (transaction) {
        transaction.reject(e);
      } else {
        frame?.close();
        throw e;
      }
    }
    throw new import_general.InternalError("Unexpected end of open");
  },
  /**
   * Normally you need to use {@link LocalActorContext.act} to work with behaviors, and you can only interact with the
   * behaviors in the actor function.  This {@link ActionContext} allows you to create offline agents that remain
   * functional for the lifespan of the node.
   *
   * Write operations will throw an error with this context.
   */
  get ReadOnly() {
    if (ReadOnly === void 0) {
      ReadOnly = LocalActorContext.open("read-only", { isolation: "ro" });
    }
    return ReadOnly;
  },
  [Symbol.toStringTag]: "LocalActorContext"
};
//# sourceMappingURL=LocalActorContext.js.map
