/* globals Twitch */
import { module } from 'qunit';
import RSVP from 'rsvp';
import startApp from 'web-client/tests/helpers/start-app';
import destroyApp from 'web-client/tests/helpers/destroy-app';
import {
  setup as overrideIframeXHRs,
  teardown as teardownIframeXHRs
} from 'web-client/tests/helpers/override-iframe-xhr';
import {
  setup as setupWebSockets,
  teardown as teardownWebSockets
} from 'web-client/tests/helpers/mock-web-sockets';
import { restoreLogin, restoreLoginModal } from 'web-client/tests/helpers/stub-login';
import getMirageServer from 'web-client/mirage/get-server';
import FakePlayer from 'web-client/tests/helpers/fake-player';
import FakeTwitchExperiments from 'web-client/tests/helpers/fake-twitch-experiments';
import MockInteractivityService from 'web-client/tests/helpers/mock-interactivity-service';
import MockTrackingService from 'web-client/tests/helpers/mock-tracking-service';
import MockNotifyService from 'web-client/tests/helpers/mock-notify-service';
import MockBitsStringsService from 'web-client/tests/helpers/mock-bits-strings-service';
import bitsString from 'web-client/tests/helpers/bits-string';
import resetStore from 'web-client/tests/helpers/reset-store';
import FakeSearch from 'web-client/tests/helpers/fake-search';
import { setupFeatures, teardownFeatures } from './utilities/feature-flagging';

const { Promise } = RSVP;

export default function (name, options = {}) {
  module(name, {
    beforeEach() {
      this.oldGoogletag = window.googletag;
      window.googletag = undefined;

      // setupWebSockets should happen before startApp to make sure we capture all socket requests
      setupWebSockets();

      // setup experiments before startApp to account for experiment values that get set in initializers
      this.originalExperiments = Twitch.experiments;
      let fakeExperiments = options.fakeExperiments || new FakeTwitchExperiments();
      Twitch.experiments = fakeExperiments;
      this.experiments = fakeExperiments;

      this.application = startApp();
      this.owner = this.application.__deprecatedInstance__;
      this.server = getMirageServer();
      this._stubbedIframes = overrideIframeXHRs();

      this.oldVideoPlayer = Twitch.video.Player;
      Twitch.video.Player = FakePlayer;
      this.oldEmbedPlayer = Twitch.embed.Player;
      Twitch.embed.Player = FakePlayer;

      this.owner.register('service:search', FakeSearch);
      this.owner.register('service:notify', MockNotifyService);
      this.owner.register('service:bits-strings', MockBitsStringsService);
      this.owner.register('helper:bits-string', bitsString);

      let features = options.features || [];

      this.featuresSetup = setupFeatures(features);

      // Stub api urls for tests while we run cdn api experiment
      Twitch.api.config.baseUrl = "https://api.twitch.tv";
      Twitch.api.config.baseUrlSecure = "https://api.twitch.tv";
      Twitch.api.config.streamsBaseUrl = "https://api.twitch.tv";
      Twitch.api.config.streamsBaseUrlSecure = "https://api.twitch.tv";
      Twitch.api.config.receiverUrl = "https://api.twitch.tv" + '/crossdomain/receiver.html?v=2';

      return this.featuresSetup.featureInjector
        .then(() => {
          return options.beforeEach && options.beforeEach.apply(this, arguments);
        })
        .then(() => {
          this._oldXhrConstructor = Twitch.api.xhrConstructor;
          Twitch.api.xhrConstructor = window.XMLHttpRequest;
          let imApiService = this.application.__container__.lookup('service:im-api');
          imApiService.set('xhrConstructor', Twitch.api.xhrConstructor);
          this.owner.register('service:interactivity', MockInteractivityService);
          this.owner.register('service:tracking', MockTrackingService);
        });
    },

    afterEach() {
      this.owner.lookup('service:interactivity').resetInvocations();
      this.owner.lookup('service:tracking').resetInvocations();
      this.owner.lookup('service:notify').resetInvocations();
      Twitch.video.Player = this.oldVideoPlayer;
      Twitch.embed.Player = this.oldEmbedPlayer;
      Twitch.experiments = this.originalExperiments;
      Twitch.api.xhrConstructor = this._oldXhrConstructor;

      let afterEach = options.afterEach && options.afterEach.apply(this, arguments);
      window.googletag = this.oldGoogleTag;

      return Promise.resolve(afterEach)
        .then(() => {
          teardownIframeXHRs(this._stubbedIframes);

          restoreLogin();
          restoreLoginModal();
          destroyApp(this.application);
          teardownWebSockets();
          resetStore();
        })
        .then(() => {
          return teardownFeatures(this.featuresSetup);
        });
    }
  });
}
