import { CartEvent } from './event';

type EventMap = Record<string, Array<(...args: any[]) => void>>;

export abstract class EventSender {
  private events: EventMap = {};

  on(event: CartEvent, listener: (...args: any[]) => void): void {
    // get string value from enum event
    if (!this.events[event]) {
      this.events[event] = [];
    }

    this.events[event].push(listener);
  }

  emit(event: CartEvent, ...args: any[]): void {
    if (this.events[event]) {
      for (const listener of this.events[event]) {
        listener(...args);
      }
    }
  }

  off(event: CartEvent, listener: (...args: any[]) => void): void {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(
        (l) => l !== listener
      );
    }
  }

  removeAllListeners(event: CartEvent): void {
    if (this.events[event]) {
      delete this.events[event];
    }
  }

  removeAllListenersAllEvents(): void {
    this.events = {};
  }

  once(event: CartEvent, listener: (...args: any[]) => void): void {
    const onceWrapper = (...args: any[]) => {
      listener(...args);
      this.off(event, onceWrapper);
    };

    this.on(event, onceWrapper);
  }
}
