export { SpiffyEvent } from './event-types';

/**
 * A singleton class for dispatching Spiffy events to the document object.
 * Provides functionality for adding default event data, managing listeners,
 * and dispatching events.
 *
 * TODO: could add observability to the listeners, would need to track listeners
 * internally.
 */
export class EventsDispatcher {
  static eventData: Record<string, any> = {};

  /**
   * Adds event data to the eventData object, which is included by default for
   * every event dispatched. E.g. could add in userId, variantInfo, etc. But
   * make sure it is JSON serializable.
   */
  static addEventData(data: Record<string, any>) {
    this.eventData = { ...this.eventData, ...data };
  }

  /**
   * Dispatches an event with the given name and detail. If includeDefault is
   * false, the default event data is excluded.
   * @param eventName - the name of the event to dispatch, should be all caps
   *   and start with SPIFFY_, e.g. "SPIFFY_FLOATING_CONTAINER_CREATED"
   * @param detail - optional parameter to include extra event data
   * @param includeDefault - optional parameter to exclude the default event
   *   data
   */
  static dispatch(
    eventName: string,
    detail: Record<string, any> = {},
    includeDefault: boolean = true,
  ) {
    const eventData = includeDefault ? { ...this.eventData, ...detail } : detail;
    const event = new CustomEvent(eventName, {
      detail: eventData,
      bubbles: true,
      composed: true,
      cancelable: false,
    });
    window.dispatchEvent(event);
  }

  static addListener(eventName: string, listener: (event: Event) => void) {
    window.addEventListener(eventName, listener, { once: false, passive: false, capture: false });
  }

  static removeListener(eventName: string, listener: (event: Event) => void) {
    window.removeEventListener(eventName, listener);
  }
}
