import { assert } from "../../../shared/src/asserts.js";
import { emptyArray } from "../../../shared/src/sentinels.js";
import { skipYields } from "./operator.js";
import { applyChange } from "./view-apply-change.js";
class ArrayView {
  #input;
  #listeners = /* @__PURE__ */ new Set();
  #schema;
  #format;
  // Synthetic "root" entry that has a single "" relationship, so that we can
  // treat all changes, including the root change, generically.
  #root;
  onDestroy;
  #dirty = false;
  #resultType = "unknown";
  #error;
  #updateTTL;
  constructor(input, format, queryComplete, updateTTL) {
    this.#input = input;
    this.#schema = input.getSchema();
    this.#format = format;
    this.#updateTTL = updateTTL;
    this.#root = { "": format.singular ? void 0 : [] };
    input.setOutput(this);
    if (queryComplete === true) {
      this.#resultType = "complete";
    } else if ("error" in queryComplete) {
      this.#resultType = "error";
      this.#error = queryComplete;
    } else {
      void queryComplete.then(() => {
        this.#resultType = "complete";
        this.#fireListeners();
      }).catch((e) => {
        this.#resultType = "error";
        this.#error = e;
        this.#fireListeners();
      });
    }
    this.#hydrate();
  }
  get data() {
    return this.#root[""];
  }
  addListener(listener) {
    assert(!this.#listeners.has(listener), "Listener already registered");
    this.#listeners.add(listener);
    this.#fireListener(listener);
    return () => {
      this.#listeners.delete(listener);
    };
  }
  #fireListeners() {
    for (const listener of this.#listeners) {
      this.#fireListener(listener);
    }
  }
  #fireListener(listener) {
    listener(this.data, this.#resultType, this.#error);
  }
  destroy() {
    this.onDestroy?.();
  }
  #hydrate() {
    this.#dirty = true;
    for (const node of skipYields(this.#input.fetch({}))) {
      applyChange(
        this.#root,
        { type: "add", node },
        this.#schema,
        "",
        this.#format
      );
    }
    this.flush();
  }
  push(change) {
    this.#dirty = true;
    applyChange(this.#root, change, this.#schema, "", this.#format);
    return emptyArray;
  }
  flush() {
    if (!this.#dirty) {
      return;
    }
    this.#dirty = false;
    this.#fireListeners();
  }
  updateTTL(ttl) {
    this.#updateTTL(ttl);
  }
}
export {
  ArrayView
};
//# sourceMappingURL=array-view.js.map
