import { PATH, STOP_IMMEDIATE_PROPAGATION, IS_TRUSTED, LISTENERS } from './constants.mjs';

let EventPhase = /*#__PURE__*/function (EventPhase) {
  EventPhase[EventPhase["NONE"] = 0] = "NONE";
  EventPhase[EventPhase["CAPTURING_PHASE"] = 1] = "CAPTURING_PHASE";
  EventPhase[EventPhase["AT_TARGET"] = 2] = "AT_TARGET";
  EventPhase[EventPhase["BUBBLING_PHASE"] = 3] = "BUBBLING_PHASE";
  return EventPhase;
}({});
const CAPTURE_MARKER = '@';
const now = typeof performance === 'undefined' ? Date.now : performance.now.bind(performance);
class Event {
  static NONE = (() => EventPhase.NONE)();
  static CAPTURING_PHASE = (() => EventPhase.CAPTURING_PHASE)();
  static AT_TARGET = (() => EventPhase.AT_TARGET)();
  static BUBBLING_PHASE = (() => EventPhase.BUBBLING_PHASE)();

  // NONE = EventPhase.NONE;
  // CAPTURING_PHASE = EventPhase.CAPTURING_PHASE;
  // AT_TARGET = EventPhase.AT_TARGET;
  // BUBBLING_PHASE = EventPhase.BUBBLING_PHASE;

  timeStamp = (() => now())();
  target = null;
  currentTarget = null;
  srcElement = null;
  bubbles = false;
  cancelable = false;
  composed = false;
  defaultPrevented = false;
  cancelBubble = false;
  eventPhase = 0;
  // private inPassiveListener = false;

  [PATH] = [];
  [STOP_IMMEDIATE_PROPAGATION] = false;
  constructor(type, options) {
    this.type = type;
    Object.defineProperty(this, IS_TRUSTED, {
      writable: true,
      value: false
    });
    if (options) {
      if (options.bubbles) this.bubbles = options.bubbles;
      if (options.cancelable) this.cancelable = options.cancelable;
      if (options.composed) this.composed = options.composed;
    }
  }
  get isTrusted() {
    return this[IS_TRUSTED];
  }
  composedPath() {
    return this[PATH];
  }
  stopPropagation() {
    this.cancelBubble = true;
  }
  stopImmediatePropagation() {
    this[STOP_IMMEDIATE_PROPAGATION] = true;
    this.cancelBubble = true;
  }
  preventDefault() {
    this.defaultPrevented = true;
  }
  set returnValue(value) {
    this.defaultPrevented = value;
  }
  get returnValue() {
    return this.defaultPrevented;
  }

  /** @deprecated */
  initEvent(type, bubbles, cancelable) {
    this.type = type;
    this.bubbles = Boolean(bubbles);
    this.cancelable = Boolean(cancelable);
  }
}
function fireEvent(event, currentTarget, phase) {
  const listeners = currentTarget[LISTENERS];
  const list = listeners?.get(`${event.type}${phase === EventPhase.CAPTURING_PHASE ? CAPTURE_MARKER : ''}`);
  if (!list) return;
  for (const listener of list) {
    event.eventPhase = event.target === currentTarget ? EventPhase.AT_TARGET : phase;
    event.currentTarget = currentTarget;
    try {
      if (typeof listener === 'object') {
        listener.handleEvent(event);
      } else {
        listener.call(currentTarget, event);
      }
    } catch (err) {
      setTimeout(thrower, 0, err);
    }
    if (event[STOP_IMMEDIATE_PROPAGATION]) break;
  }
}
function thrower(error) {
  throw error;
}

export { CAPTURE_MARKER, Event, EventPhase, fireEvent };
