/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { MaybePromise, StorageContext } from "@matter/general";
class EndpointStore {
  initialValues = /* @__PURE__ */ new Map();
  #storage;
  #knownBehaviors = /* @__PURE__ */ new Set();
  constructor(storage) {
    this.#storage = storage;
  }
  /**
   * Retrieve the primary key used to identify this store.
   */
  get id() {
    return this.storage.thisContexts[this.storage.thisContexts.length - 1];
  }
  /**
   * Extract initial values for a behavior.  Derivatives invoke this when instantiating a store.  The values are then
   * owned by the store.
   */
  consumeInitialValues(behaviorId) {
    const initialValues = this.initialValues.get(behaviorId);
    if (initialValues !== void 0) {
      this.initialValues.delete(behaviorId);
    }
    return initialValues;
  }
  /**
   * Patch values.  Keyed by {@link Behavior.id} then property name.
   *
   * See {@link Datasource.Store.set} for the patch semantics the individual structs use.
   *
   * When {@link sharedTx} is provided, writes go through it and the caller owns the transaction lifecycle (no
   * commit/dispose here).
   */
  async set(values, sharedTx) {
    const ownTx = sharedTx === void 0;
    let tx;
    if (ownTx) {
      const maybeTx = this.storage.begin();
      tx = MaybePromise.is(maybeTx) ? await maybeTx : maybeTx;
    } else {
      tx = sharedTx;
    }
    try {
      const txContext = new StorageContext(tx, this.storage.thisContexts);
      for (const behaviorId in values) {
        const behaviorValues = values[behaviorId];
        const behaviorStorage = txContext.createContext(behaviorId);
        if (behaviorValues === void 0) {
          if (this.knownBehaviors.has(behaviorId)) {
            await behaviorStorage.clearAll();
            this.knownBehaviors.delete(behaviorId);
          }
          continue;
        }
        if (!this.knownBehaviors.has(behaviorId)) {
          this.knownBehaviors.add(behaviorId);
        }
        const toSave = {};
        let keysToSave = 0;
        for (const key in behaviorValues) {
          const value = behaviorValues[key];
          if (value === void 0) {
            await behaviorStorage.delete(key);
          } else {
            toSave[key] = value;
            keysToSave++;
          }
        }
        if (keysToSave > 0) {
          await behaviorStorage.set(toSave);
        }
      }
      if (ownTx) {
        tx.commit();
      }
    } catch (e) {
      if (ownTx) {
        tx[Symbol.dispose]();
      }
      throw e;
    }
  }
  /**
   * Description used in diagnostic messages.
   */
  toString() {
    return `storage:${this.#storage.thisContexts.join(".")}`;
  }
  /**
   * IDs for behaviors persisted in this store.
   */
  get knownBehaviors() {
    return this.#knownBehaviors;
  }
  /**
   * Load the store with persisted values.
   */
  async load() {
    this.#knownBehaviors = new Set(await this.storage.contexts());
    for (const behaviorId of this.#knownBehaviors) {
      const behaviorValues = {};
      this.initialValues.set(behaviorId, behaviorValues);
      const behaviorStorage = this.storage.createContext(behaviorId);
      const storedValues = await behaviorStorage.values();
      for (const [key, value] of Object.entries(storedValues)) {
        if (value !== void 0) {
          behaviorValues[key] = value;
        }
      }
    }
  }
  /**
   * Remove all persisted information for the {@link Endpoint}.
   */
  erase() {
    return this.storage.clearAll();
  }
  /**
   * Remove all persisted information for a single behavior on the {@link Endpoint}.
   */
  eraseStoreForBehavior(behaviorId) {
    return this.storage.createContext(behaviorId).clearAll();
  }
  get storage() {
    return this.#storage;
  }
}
export {
  EndpointStore
};
//# sourceMappingURL=EndpointStore.js.map
