import { ArraySet } from "./ArraySet.mjs";
import { maybeCaptureParent } from "./capture.mjs";
import { EMPTY_ARRAY, equals } from "./helpers.mjs";
import { HistoryBuffer } from "./HistoryBuffer.mjs";
import { advanceGlobalEpoch, atomDidChange, globalEpoch } from "./transactions.mjs";
import { RESET_VALUE } from "./types.mjs";
class _Atom {
  constructor(name, current, options) {
    this.name = name;
    this.current = current;
    this.isEqual = options?.isEqual ?? null;
    if (!options)
      return;
    if (options.historyLength) {
      this.historyBuffer = new HistoryBuffer(options.historyLength);
    }
    this.computeDiff = options.computeDiff;
  }
  isEqual;
  computeDiff;
  lastChangedEpoch = globalEpoch;
  children = new ArraySet();
  historyBuffer;
  __unsafe__getWithoutCapture() {
    return this.current;
  }
  get value() {
    maybeCaptureParent(this);
    return this.current;
  }
  set(value, diff) {
    if (this.isEqual?.(this.current, value) ?? equals(this.current, value)) {
      return this.current;
    }
    advanceGlobalEpoch();
    if (this.historyBuffer) {
      this.historyBuffer.pushEntry(
        this.lastChangedEpoch,
        globalEpoch,
        diff ?? this.computeDiff?.(this.current, value, this.lastChangedEpoch, globalEpoch) ?? RESET_VALUE
      );
    }
    this.lastChangedEpoch = globalEpoch;
    const oldValue = this.current;
    this.current = value;
    atomDidChange(this, oldValue);
    return value;
  }
  update(updater) {
    return this.set(updater(this.current));
  }
  getDiffSince(epoch) {
    maybeCaptureParent(this);
    if (epoch >= this.lastChangedEpoch) {
      return EMPTY_ARRAY;
    }
    return this.historyBuffer?.getChangesSince(epoch) ?? RESET_VALUE;
  }
}
function atom(name, initialValue, options) {
  return new _Atom(name, initialValue, options);
}
function isAtom(value) {
  return value instanceof _Atom;
}
export {
  _Atom,
  atom,
  isAtom
};
//# sourceMappingURL=Atom.mjs.map
