require('jsdom-global')();

import expect from 'expect';

import { partialPropMountWrapper } from 'mtest/helpers/partialPropWrappers';
import TwitchPlayerMock, {
  ITwitchPlayerMock,
} from 'mtest/helpers/twitchPlayerMock';

import {
  BaseVideoPlayer,
  BaseVideoPlayerProps,
} from 'mweb/common/components/videoPlayer/base';

class TestVideoPlayer extends BaseVideoPlayer<BaseVideoPlayerProps> {
  player: ITwitchPlayerMock;

  trackPlayerReady = () => undefined;
  trackPlayerPlaying = () => undefined;

  get playerParams(): Partial<Twitch.PlayerOptions> {
    return this.props;
  }

  setSource(): void {
    return;
  }
}

class FailingTestVideoPlayer extends TestVideoPlayer {
  trackPlayerReady = () => undefined;
  trackPlayerPlaying = () => undefined;

  protected buildPlayer(): void {
    return;
  }
}

describe('<VideoPlayer />', () => {
  before(() => {
    window.Twitch = {
      Player: TwitchPlayerMock as Twitch.PlayerGlobal,
    };
  });

  after(() => {
    delete window.Twitch;
  });

  const DEFAULTS_PROPS: BaseVideoPlayerProps = {
    sessionID: 'alecleewasnothere',
    hostChannel: 'voxel',
  };

  it('initializes the player properly and unregisters READY listener on unmount', () => {
    const playerWrapper = partialPropMountWrapper(
      TestVideoPlayer,
      DEFAULTS_PROPS,
    )();
    const videoPlayer = playerWrapper.instance() as TestVideoPlayer;
    expect(videoPlayer.player.width).toEqual('100%');
    expect(videoPlayer.player.height).toEqual('100%');
    expect(videoPlayer.player.branding).toEqual(false);
    expect(videoPlayer.player.channelInfo).toEqual(false);
    expect(videoPlayer.player.allowfullscreen).toEqual(true);
    expect(videoPlayer.player.playsinline).toEqual(true);
    expect(videoPlayer.player.muted).toEqual(true);
    expect(videoPlayer.player.autoplay).toEqual(true);

    expect(videoPlayer.player.listeners[window.Twitch.Player.READY]).toExist();
    expect(
      videoPlayer.player.listeners[window.Twitch.Player.READY].length,
    ).toEqual(2);
    expect(
      videoPlayer.player.listeners[window.Twitch.Player.PLAYING],
    ).toExist();
    expect(
      videoPlayer.player.listeners[window.Twitch.Player.PLAYING].length,
    ).toEqual(1);

    // reachable because callbacks are immediately invoked by the mock player
    expect(videoPlayer.player.trackingProperties).toEqual({
      app_session_id: DEFAULTS_PROPS.sessionID,
      benchmark_session_id: DEFAULTS_PROPS.sessionID,
      client_app: 'mobile_web',
      host_channel: DEFAULTS_PROPS.hostChannel,
    });

    playerWrapper.unmount();
    expect(
      videoPlayer.player.listeners[window.Twitch.Player.READY],
    ).toNotExist();
    expect(
      videoPlayer.player.listeners[window.Twitch.Player.PLAYING],
    ).toNotExist();
  });

  it('survives buildPlayer not successfully creating a player', () => {
    const playerWrapper = partialPropMountWrapper(
      FailingTestVideoPlayer,
      DEFAULTS_PROPS,
    )();
    expect(playerWrapper.find('.player-holder')).toExist();
    const videoPlayer = playerWrapper.instance() as FailingTestVideoPlayer;
    expect(videoPlayer.player).toNotExist();
  });
});
