interface Listeners {
  [event: string]: Function[];
}

export interface ITwitchPlayerMock extends Twitch.Player {
  height: number | string | undefined;
  width: number | string | undefined;
  branding: boolean | undefined;
  channelInfo: boolean | undefined;
  allowfullscreen: boolean | undefined;
  playsinline: boolean | undefined;
  autoplay: boolean | undefined;
  channelName: string | undefined;
  videoID: string | undefined;
  muted: boolean | undefined;
  seekTimestamp: number;
  listeners: Listeners;
  trackingProperties: Twitch.TrackingProperties;
}

export default class TwitchPlayerMock implements ITwitchPlayerMock {
  public static READY: Twitch.EVENT_READY = 'ready';
  public static PLAY: Twitch.EVENT_PLAY = 'play';
  public static PLAYING: Twitch.EVENT_PLAYING = 'playing';
  public static PAUSE: Twitch.EVENT_PAUSE = 'pause';
  public static ENDED: Twitch.EVENT_ENDED = 'ended';
  public static ONLINE: Twitch.EVENT_ONLINE = 'online';
  public static OFFLINE: Twitch.EVENT_OFFLINE = 'offline';
  public static TIMEUPDATE: Twitch.EVENT_TIMEUPDATE = 'timeupdate';

  height: number | string | undefined;
  width: number | string | undefined;
  branding: boolean | undefined;
  channelInfo: boolean | undefined;
  allowfullscreen: boolean | undefined;
  playsinline: boolean | undefined;
  autoplay: boolean | undefined;
  channelName: string | undefined;
  videoID: string | undefined;
  muted: boolean | undefined;
  seekTimestamp: number;
  listeners: Listeners = {};
  trackingProperties: Twitch.TrackingProperties = {};

  constructor(_ref: HTMLDivElement, options: Twitch.PlayerOptions) {
    this.height = options.height;
    this.width = options.width;
    this.branding = options.branding;
    this.channelInfo = options.channelInfo;
    this.allowfullscreen = options.allowfullscreen;
    this.playsinline = options.playsinline;
    this.autoplay = options.autoplay;
    this.videoID = (options as Twitch.VODPlayerOptions).video;
    this.muted = options.muted;
    this.channelName = (options as Twitch.ChannelPlayerOptions).channel;
    if ((options as Twitch.VODPlayerOptions).time != null) {
      this.seekTimestamp = 60;
    }
  }

  addEventListener(eventName: Twitch.PlayerEvent, callback: Function): void {
    if (this.listeners[eventName]) {
      this.listeners[eventName].push(callback);
    } else {
      this.listeners[eventName] = [callback];
    }
    callback();
  }

  removeEventListener(eventName: Twitch.PlayerEvent, callback: Function): void {
    if (!this.listeners[eventName]) {
      return;
    }

    this.listeners[eventName] = this.listeners[eventName].filter(
      cb => cb !== callback,
    );
    if (this.listeners[eventName].length === 0) {
      delete this.listeners[eventName];
    }
  }

  setChannel(channelName: Twitch.ChannelName): void {
    this.channelName = channelName;
    this.videoID = undefined;
  }

  setVideo(videoID: Twitch.VideoId): void {
    this.videoID = videoID;
    this.channelName = undefined;
  }

  seek(timestamp: number): void {
    this.seekTimestamp = timestamp;
  }

  setTrackingProperties(trackingProperties: Twitch.TrackingProperties): void {
    this.trackingProperties = trackingProperties;
  }

  // unused methods stubbed to satisfy interface
  isPaused(): boolean {
    return false;
  }
  getCurrentTime(): number {
    return 0;
  }
  pause(): void {
    return;
  }
  play(): void {
    return;
  }
}
