// src/js-tools/js-utils/util/event.ts
var EventHandler = class {
  constructor() {
    this._listeners = {};
    // Identity-only tracking of original (unwrapped) callbacks for addListenerOnce.
    // `object` is the widest type compatible with all listener variants — functions
    // are objects in JS and Set uses === for membership.
    this._onceOriginals = /* @__PURE__ */ new Map();
  }
  addListener(type, callback) {
    let listeners = this._listeners[type];
    if (!listeners) {
      listeners = [];
      this._listeners[type] = listeners;
    }
    if (listeners.indexOf(callback) !== -1) {
      throw new Error("Listener callback already exists.");
    }
    listeners.push(callback);
    return () => {
      this.removeListener(type, callback);
    };
  }
  addListenerOnce(type, callback) {
    let listeners = this._listeners[type];
    if (!listeners) {
      listeners = [];
      this._listeners[type] = listeners;
    }
    let originals = this._onceOriginals.get(type);
    if (!originals) {
      originals = /* @__PURE__ */ new Set();
      this._onceOriginals.set(type, originals);
    }
    if (originals.has(callback)) {
      throw new Error("Listener callback already exists.");
    }
    originals.add(callback);
    const wrappedCallback = (e) => {
      callback(e);
      originals.delete(callback);
      this.removeListener(type, wrappedCallback);
    };
    listeners.push(wrappedCallback);
  }
  removeListener(type, callback) {
    const listeners = this._listeners[type];
    if (!listeners) {
      throw new Error(
        `Cannot find listeners for event type ${String(type)}`
      );
    }
    const index = listeners.indexOf(callback);
    if (index === -1) {
      throw new Error("Listener callback cannot be found");
    }
    listeners.splice(index, 1);
  }
  dispatchEvent(type, ...args) {
    const listeners = this._listeners[type];
    if (listeners) {
      if (args[0]) {
        const event = {
          type,
          target: this,
          value: args[0]
        };
        [...listeners].forEach((listener) => listener(event));
      } else {
        const event = {
          type,
          target: this
        };
        [...listeners].forEach((listener) => listener(event));
      }
    }
  }
};

export {
  EventHandler
};
