/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  FilesystemStorageDriver,
  fromJson,
  MemoryStorageDriver,
  Seconds,
  StorageError,
  Time,
  toJson
} from "@matter/general";
import { readFileSync } from "node:fs";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
class JsonFileStorageDriver extends FilesystemStorageDriver {
  static id = "json";
  /** We store changes after a value was set to the storage, but not more often than this setting (in ms). */
  static commitDelay = Seconds.one;
  committed = Promise.resolve();
  #commitTimer = Time.getTimer("Storage commit", JsonFileStorageDriver.commitDelay, () => this.#commit());
  #closed = false;
  #resolveCommitted;
  #path;
  #store;
  constructor(namespaceOrPath) {
    super(typeof namespaceOrPath === "string" || namespaceOrPath === void 0 ? void 0 : namespaceOrPath);
    this.#path = typeof namespaceOrPath === "string" ? namespaceOrPath : namespaceOrPath !== void 0 ? join(this.root.directory.path, "storage.json") : "";
    this.#store = new MemoryStorageDriver();
  }
  static async create(namespace, _descriptor) {
    const storage = new JsonFileStorageDriver(namespace);
    try {
      await storage.initialize();
    } catch (error) {
      await storage.close().catch(() => {
      });
      throw error;
    }
    return storage;
  }
  get initialized() {
    return this.#store.initialized;
  }
  async initialize() {
    if (this.initialized) throw new StorageError("Storage already initialized!");
    await super.initialize();
    let data = {};
    try {
      data = fromJson(readFileSync(this.#path, "utf-8"));
    } catch (error) {
      if (error.code !== "ENOENT") {
        throw error;
      }
    }
    this.#store = new MemoryStorageDriver(data);
    this.#store.initialize();
  }
  #triggerCommit() {
    if (!this.#commitTimer.isRunning) {
      this.committed = new Promise((resolve) => {
        this.#resolveCommitted = resolve;
      });
      this.#commitTimer.start();
    }
  }
  get(contexts, key) {
    return this.#store.get(contexts, key);
  }
  set(contexts, keyOrValues, value) {
    this.#store.set(contexts, keyOrValues, value);
    this.#triggerCommit();
  }
  delete(contexts, key) {
    this.#store.delete(contexts, key);
    this.#triggerCommit();
  }
  keys(contexts) {
    return this.#store.keys(contexts);
  }
  values(contexts) {
    return this.#store.values(contexts);
  }
  contexts(contexts) {
    return this.#store.contexts(contexts);
  }
  clearAll(contexts) {
    this.#store.clearAll(contexts);
  }
  openBlob(contexts, key) {
    return this.#store.openBlob(contexts, key);
  }
  writeBlobFromStream(contexts, key, stream) {
    return this.#store.writeBlobFromStream(contexts, key, stream);
  }
  async #commit() {
    if (!this.initialized || this.#closed) return;
    if (this.#commitTimer.isRunning) {
      this.#commitTimer.stop();
    }
    try {
      await writeFile(this.#path, toJson(this.#store.data, 1), "utf-8");
    } finally {
      if (this.#resolveCommitted !== void 0) {
        this.#resolveCommitted();
      }
    }
  }
  async close() {
    this.#commitTimer.stop();
    await this.#commit();
    await this.#store.close();
    this.#closed = true;
    await super.close();
  }
}
export {
  JsonFileStorageDriver
};
//# sourceMappingURL=JsonFileStorageDriver.js.map
