/* global Twitch */
import { test } from 'qunit';
import moduleForAcceptance from 'web-client/tests/helpers/module-for-acceptance';
import indexScenario from 'web-client/mirage/scenarios/index';
import IndexPage from 'web-client/tests/pages/index';
import { stubLogin } from 'web-client/tests/helpers/stub-login';
import { lastPlayerInstance } from 'web-client/tests/helpers/fake-player';

moduleForAcceptance('Acceptance | / (index)', {
  beforeEach() {
    let { featuredStreams } = indexScenario(this.server);
    this.featuredStreams = featuredStreams;
    this.page = IndexPage.create();
  }
});

test('renders top & featured games', function(assert) {
  assert.expect(2);

  visit(this.page.url());

  andThen(() => {
    assert.equal(this.page.hasTopGames().length, 10, 'displays 10 games on front page');
    assert.equal(this.page.hasFeaturedGames().length, 2, 'displays 2 featured games on front page');
  });
});

test('displays signup/login links when logged out', function(assert) {
  assert.expect(2);

  visit(this.page.url());
  andThen(() => {
    assert.ok(this.page.hasLoginLink(), 'displays login link in header');
    assert.ok(this.page.hasSignupLink(), 'displays signup link in header');
  });
});

test('displays username when logged in', function(assert) {
  assert.expect(1);

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());
  andThen(() => {
    let displayName = this.page.hasCurrentUserDisplayName();
    assert.stringIncludes(displayName, 'testUser', 'the displayName appears in the menu');
  });
});

test('displays facebook, twitter, social media links', function(assert) {
  stubLogin({
    id: '42',
    name: 'primeUser',
    username: 'primeUser',
    has_premium: true
  });

  assert.expect(3);

  visit(this.page.url());
  andThen(() => {
    assert.ok(this.page.hasFacebookButton(), 'displays facebook button');
    assert.ok(this.page.hasTwitterButton(), 'displays twitter button');
    assert.ok(this.page.hasBlogButton(), 'displays blog button');
  });
});

test('tracks carousel_display event', function(assert) {
  assert.expect(1);
  visit(this.page.url());

  andThen(() => {
    assert.trackEvent('carousel_display', event => {
      let keys = Object.keys(event.data).sort();
      assert.deepEqual(keys, [
        'carousel_slot_0_channel',
        'carousel_slot_0_game',
        'carousel_slot_0_priority',
        'carousel_slot_1_channel',
        'carousel_slot_1_game',
        'carousel_slot_1_priority',
        'carousel_slot_2_channel',
        'carousel_slot_2_game',
        'carousel_slot_2_priority',
        'carousel_slot_3_channel',
        'carousel_slot_3_game',
        'carousel_slot_3_priority',
        'carousel_slot_4_channel',
        'carousel_slot_4_game',
        'carousel_slot_4_priority',
        'carousel_slot_5_channel',
        'carousel_slot_5_game',
        'carousel_slot_5_priority',
        'platform'
      ]);
    });
  });
});

test('changing carousel channel', function(assert) {
  assert.expect(5);
  visit(this.page.url());

  andThen(() => {
    assert.equal(this.page.getActiveIndex(), 0, 'first element is active');
    let $secondChannel = this.page.getCarouselItem(1);
    click($secondChannel.children('a'));
  });

  andThen(() => {
    assert.trackEvent('frontpage-carousel-click');
    assert.equal(this.page.getActiveIndex(), 1, 'second channel is active');
  });

  click(this.page.activeChannelTitle);

  andThen(() => {
    assert.equal(currentURL(), `/${this.featuredStreams[1].name}`, 'transitions to channel route');
    assert.equal(currentRouteName(), 'channel.index.index');
  });
});

test('shows ps4 streams', function(assert) {
  assert.expect(4);

  visit(this.page.url());

  let opts = this.page.ps4;
  andThen(() => {
    assert.ok(this.page.isFound(opts.title), 'title');
    assert.equal(find(opts.streams).length, 6, '6 streams');
  });

  click(opts.allChannelsLink);

  andThen(() => {
    assert.equal(currentURL(), '/directory/all/ps4', 'url');
    assert.equal(currentRouteName(), 'directory.channels.psFour', 'route');
  });
});

test('shows xbox streams', function(assert) {
  assert.expect(4);

  visit(this.page.url());

  let opts = this.page.xbox;
  andThen(() => {
    assert.ok(this.page.isFound(opts.title), 'title');
    assert.equal(find(opts.streams).length, 6, '6 streams');
  });

  click(opts.allChannelsLink);

  andThen(() => {
    assert.equal(currentURL(), '/directory/all/xb1', 'url');
    assert.equal(currentRouteName(), 'directory.channels.xbOne', 'route');
  });
});

test('shows live streams', function(assert) {
  assert.expect(4);

  visit(this.page.url());

  let opts = this.page.live;
  andThen(() => {
    assert.ok(this.page.isFound(opts.title), 'title');
    assert.equal(find(opts.streams).length, 6, '6 streams');
  });

  click(opts.allChannelsLink);

  andThen(() => {
    assert.equal(currentURL(), '/directory/all', 'url');
    assert.equal(currentRouteName(), 'directory.channels.all', 'route');
  });
});

test('displays ad slots', function(assert) {
  assert.expect(5);

  Twitch.asyncAds.ready = (callback) => {
    callback({ enabled: true });
  };

  visit(this.page.url());

  andThen(() => {
    assert.ok(this.page.isFound('#Twitch_FPMedRect_holder'), '#Twitch_FPMedRect_holder div exists');
    assert.ok(this.page.isFound('#Twitch_FPopaBanner_holder'), '#Twitch_FPopaBanner_holder div exists');
    assert.ok(this.page.isFound('#Twitch_FPTakeoverSkinv2_holder'), '#Twitch_FPTakeoverSkinv2_holder div exists');
    assert.ok(this.page.isFound('#Twitch_FP970Bottom_holder'), '#Twitch_FP970Bottom_holder div exists');
    assert.ok(this.page.isFound('#sizzle_strip'), '#sizzle_strip div exists');
  });
});

test('displays alternate <link>s', function(assert) {
  assert.expect(2);

  visit(this.page.url());

  andThen(() => {
    assert.ok(this.page.isFound('link[href^=android-app]', 'head'), 'contains a <link href="android-app://...">');
    assert.ok(this.page.isFound('link[href^=ios-app]', 'head'), 'contains a <link href="ios-app://...">');
  });
});

test('tracks interactivity', function (assert) {
  assert.expect(2);

  visit(this.page.url());

  andThen(() => {
    // Invoke the player's "contentShowing" event to trigger its "reportInteractive" method
    lastPlayerInstance.listeners['contentShowing'].forEach(function (listener) {
      listener();
    });
    assert.trackInteractivity('index');
  });

  andThen(() => { // Run in a separate andThen() because this gets fired from a resolved promise
    assert.trackBenchmarkEvent('complete_transition');
  });
});

test('does not render pulse', function (assert) {
  assert.expect(1);

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());

  let opts = this.page.pulse;
  andThen(() => {
    assert.notOk(this.page.isFound(opts.title), 'title');
  });
});

moduleForAcceptance('Acceptance | / (index with Pulse)', {
  beforeEach() {
    this.server.get(`http://api.twitch.tv/kraken/feed/posts`, () => {
      return {
        _disabled: false,
        _cursor: "",
        _topic: "",
        posts: []
      };
    });
    this.page = IndexPage.create();
  }
});

test('renders Pulse', function (assert) {
  assert.expect(1);

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());

  let opts = this.page.pulse;
  andThen(() => {
    assert.ok(this.page.isFound(opts.title), 'title');
  });
});

test('displays signup/login links when logged out', function(assert) {
  assert.expect(2);

  visit(this.page.url());
  andThen(() => {
    assert.ok(this.page.hasLoginLink(), 'displays login link in header');
    assert.ok(this.page.hasSignupLink(), 'displays signup link in header');
  });
});

test('displays username when logged in', function(assert) {
  assert.expect(1);

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());
  andThen(() => {
    let displayName = this.page.hasCurrentUserDisplayName();
    assert.stringIncludes(displayName, 'testUser', 'the displayName appears in the menu');
  });
});

test('does not render top & featured games, live streams, ps4 streams, or xbox streams', function (assert) {
  assert.expect(5);

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());

  andThen(() => {
    assert.equal(this.page.hasTopGames().length, undefined, 'displays no games on front page');
    assert.equal(this.page.hasFeaturedGames().length, undefined, 'displays no featured games on front page');
    assert.notOk(this.page.isFound(this.page.live.title), 'title');
    assert.notOk(this.page.isFound(this.page.ps4.title), 'title');
    assert.notOk(this.page.isFound(this.page.xbox.title), 'title');
  });
});

test('tracks interactivity with Pulse', function (assert) {
  assert.expect(4);

  let service = this.owner.lookup('service:interactivity');

  stubLogin({
    id: '1337',
    name: 'testUser',
    login: 'testUser'
  });

  visit(this.page.url());

  andThen(() => {
    let isInteractive = service._monitorInvocations[0].isInteractive;

    // Invoke the player's "contentShowing" event to trigger its "reportInteractive" method
    lastPlayerInstance.listeners['contentShowing'].forEach(function (listener) {
      listener();
    });
    assert.trackInteractivity('index');

    let interactive = isInteractive({ 'front-page/carousel-player': true });
    assert.notOk(interactive, 'should not return true because newsfeed was not rendered');

    interactive = isInteractive({
      'front-page/carousel-player': true,
      'twitch-feed/composer': true,
      'front-page/news-feed/streams': true
    });
    assert.ok(interactive, 'should return true because all required components were rendered');
  });

  andThen(() => { // Run in a separate andThen() because this gets fired from a resolved promise
    assert.trackBenchmarkEvent('complete_transition');
  });
});

