import moduleForComponent from 'web-client/tests/helpers/module-for-component';
import { test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import wait from 'ember-test-helpers/wait';
import AutohostUI from 'web-client/tests/pages/autohost-settings';
import {
  MAX_RECOMMENDED_CHANNELS,
  ONBOARDING_SOURCE,
  ADDED_BACK_SOURCE,
  ONBOARDING_LOCATION,
  SETTINGS_LOCATION
} from 'web-client/components/autohost-settings';
import { stubLogin } from '../../helpers/stub-login';
import { AuthenticatedSession } from 'web-client/tests/helpers/mock-session-service';
import MockTrackingService from 'web-client/tests/helpers/mock-tracking-service';
import MockAutohostService from 'web-client/tests/helpers/mock-autohost-service';

moduleForComponent('autohost-settings', {
  beforeEach() {
    this.register('service:session', AuthenticatedSession);
    this.register('service:tracking', MockTrackingService);
    this.register('service:autohost', MockAutohostService);
    this.ui = new AutohostUI(this);
  }
});

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

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('settings', {enabled: true});

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.enabledSwitchIsActive(), true, 'enabled');
    assert.equal(this.ui.teamSwitchIsActive(), false, 'no team host');
    return wait();
  });
});

test('toggles enabled', function (assert) {
  assert.expect(2);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('settings', {enabled: false});

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    this.ui.enabledSwitch().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.enabledSwitchIsActive(), true, 'enabled');
    assert.trackEvent('autohost_toggle', { new_value: true });
    return wait();
  });
});

test('toggles team host', function (assert) {
  assert.expect(2);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('settings', {team_host: false});

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    this.ui.teamSwitch().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.teamSwitchIsActive(), true, 'enabled');
    assert.trackEvent('autohost_team_toggle', { new_value: true });
    return wait();
  });
});

test('toggles recommended host', function (assert) {
  assert.expect(2);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('settings', {recommended_host: false});

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    this.ui.recommendedSwitch().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.recommendedSwitchIsActive(), true, 'enabled');
    assert.trackEvent('autohost_similar_channels_toggle', { new_value: true });
    return wait();
  });
});

test('view recommended opens view', function (assert) {
  assert.expect(1);

  stubLogin();

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    this.ui.viewRecommended().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.similarChannelsView().length, 1, 'similar channels view appears');
    return wait();
  });
});

test('switches host strategy', function (assert) {
  assert.expect(6);

  stubLogin();

  let autohost = this.owner.lookup('service:autohost');
  autohost.set('settings', {strategy: 'ordered'});

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.orderedStrategyButton().is(':checked'), true, 'ordered strategy checked');
    assert.equal(this.ui.randomStrategyButton().is(':checked'), false, 'random strategy not checked');
    this.ui.randomStrategyButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.orderedStrategyButton().is(':checked'), false, 'ordered strategy not checked');
    assert.equal(this.ui.randomStrategyButton().is(':checked'), true, 'random strategy checked');
    this.ui.orderedStrategyButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.orderedStrategyButton().is(':checked'), true, 'ordered strategy checked');
    assert.equal(this.ui.randomStrategyButton().is(':checked'), false, 'random strategy not checked');
    return wait();
  });
});

test('no channels shows add button, opens search', function (assert) {
  assert.expect(2);

  stubLogin();

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.addChannelsButton().length, 1, 'add channels button appears');
    this.ui.addChannelsButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.searchInput().length, 1, 'search appears');
    return wait();
  });
});

test('onboarding dismiss', function (assert) {
  assert.expect(3);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('autoHostedBy', [
    { _id: 1, name: 'autohosted_by-1' },
    { _id: 2, name: 'autohosted_by-2' }
  ]);
  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.addChannelsButton().length, 0, 'no add channels button');
    assert.equal(this.ui.onboardingRecommendedChannels().length, 2, 'shows recommended results');
    this.ui.dismissOnboardingButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.onboardingRecommendedChannels().length, 0, 'recommended results gone');
    return wait();
  });
});

test('onboarding dismiss if all recs added', function (assert) {
  assert.expect(5);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('autoHostedBy', [
    { _id: 1, name: 'autohosted_by-1' },
    { _id: 2, name: 'autohosted_by-2' }
  ]);
  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.onboardingRecommendedChannels().length, 2, 'shows recommended results');

    this.ui.onboardingRecommendedAddButtons()[0].click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.targets().length, 1, '1 channel added');
    assert.trackEvent('autohost_channel_update', { location: ONBOARDING_LOCATION, source: ONBOARDING_SOURCE });
    this.ui.onboardingRecommendedAddButtons()[0].click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.targets().length, 2, 'channels there');
    assert.equal(this.ui.onboardingRecommendedChannels().length, 0, 'recommended results gone');
    return wait();
  });
});

test('onboarding dismiss if other channel added', function (assert) {
  assert.expect(5);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('autoHostedBy', [
    { _id: 1, name: 'autohosted_by-1' },
    { _id: 2, name: 'autohosted_by-2' }
  ]);
  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.onboardingRecommendedChannels().length, 2, 'shows recommended results');
    this.ui.openSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.recommendedResults().length, 2, 'shows search recommended results');
    this.ui.searchRecommendedResultsAddButtons()[0].click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.targets().length, 1, 'channel there');
    assert.equal(this.ui.onboardingRecommendedChannels().length, 0, 'onboarding gone');
    assert.trackEvent('autohost_channel_update', { location: SETTINGS_LOCATION, source: ADDED_BACK_SOURCE });
    return wait();
  });
});

test('search can be opened and closed', function (assert) {
  assert.expect(8);

  stubLogin();

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.openSearchButton().length, 1, 'open search appears');
    assert.equal(this.ui.closeSearchButton().length, 0, 'no close search appears');
    this.ui.openSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.searchInput().length, 1, 'search appears');
    assert.equal(this.ui.closeSearchButton().length, 1, 'close search appears');
    assert.equal(this.ui.openSearchButton().length, 0, 'no open search appears');
    this.ui.closeSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.searchInput().length, 0, 'search is closed');
    assert.equal(this.ui.openSearchButton().length, 1, 'open search appears');
    assert.equal(this.ui.closeSearchButton().length, 0, 'no close search appears');
    return wait();
  });
});

test('recommended channels in search (less than max)', function(assert) {
  assert.expect(4);

  stubLogin();
  this.server.create('channel', { name: 'favorite' });
  this.server.create('channel', { name: 'similar' });

  let autohost = this.owner.lookup('service:autohost');
  autohost.set('autoHostedBy', [
    { _id: 1, name: 'autohosted_by' }
  ]);

  this.render(hbs`{{autohost-settings showOnboarding=false}}`);

  return wait().then(() => {
    this.ui.openSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.recommendedResults().length, 3, 'shows recommended results');
    assert.elementText($(this.ui.recommendedResults()[0]).find('.card__info'), 'Channel you watch', 'first rec is favorite');
    assert.elementText($(this.ui.recommendedResults()[1]).find('.card__info'), 'Auto hosts you', 'second rec is autohosted by');
    assert.elementText($(this.ui.recommendedResults()[2]).find('.card__info'), 'Similar channel', 'third rec is similar');
    return wait();
  });
});

test('recommended channels in search (all one type)', function(assert) {
  assert.expect(1);

  stubLogin();
  this.server.createList('channel', MAX_RECOMMENDED_CHANNELS + 2, { name: 'similar' });

  this.render(hbs`{{autohost-settings showOnboarding=false}}`);

  return wait().then(() => {
    this.ui.openSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.recommendedResults().length, MAX_RECOMMENDED_CHANNELS, 'shows recommended results');
    return wait();
  });
});

test('recommended channels in search (uneven distribution)', function(assert) {
  assert.expect(4);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('autoHostedBy', [
    { _id: 1, name: 'autohosted_by', display_name: 'user1' }
  ]);

  this.server.create('channel', { name: 'favorite', display_name: 'user2' });
  this.server.create('channel', { name: 'favorite', display_name: 'user3' });
  this.server.create('channel', { name: 'favorite', display_name: 'user4' });
  this.server.create('channel', { name: 'favorite', display_name: 'user5' });
  this.server.create('channel', { name: 'favorite', display_name: 'user6' });
  this.server.create('channel', { name: 'favorite', display_name: 'user7' });
  this.server.create('channel', { name: 'favorite', display_name: 'user8' });
  this.server.create('channel', { name: 'favorite', display_name: 'user9' });
  this.server.create('channel', { name: 'similar', display_name: 'user10' });
  this.server.create('channel', { name: 'similar', display_name: 'user11' });
  this.render(hbs`{{autohost-settings showOnboarding=false}}`);

  return wait().then(() => {
    this.ui.openSearchButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.recommendedResults().length, MAX_RECOMMENDED_CHANNELS, 'shows recommended results');
    assert.elementText($(this.ui.recommendedResults()[5]).find('.card__info'), 'Channel you watch', 'favorites first');
    assert.elementText($(this.ui.recommendedResults()[6]).find('.card__info'), 'Auto hosts you', 'autohosted by next');
    assert.elementText($(this.ui.recommendedResults()[7]).find('.card__info'), 'Similar channel', 'similar last');
    return wait();
  });
});

test('deletes channel', function (assert) {
  assert.expect(6);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('list', [
    { _id: 1, name: 'user1', display_name: 'user1' }
  ]);

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.addChannelsButton().length, 0, 'no add channels button');
    assert.equal(this.ui.deleteTargetButton().length, 1, 'delete button is there');
    this.ui.deleteTargetButton().click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.addChannelsButton().length, 1, 'add channels button there');
    assert.equal(this.ui.targets().length, 0, 'no more channels');
    assert.trackEvent('autohost_channel_update', { action: 'removed' });
    autohost.set('list', [
      { _id: 1, name: 'user1', display_name: 'user1' }
    ]);
    return wait();
  }).then(() => {
    assert.equal(this.ui.addChannelsButton().length, 0, 'no add channels button');
    return wait();
  });
});

test('moves channels around', function (assert) {
  assert.expect(13);

  stubLogin();
  let autohost = this.owner.lookup('service:autohost');
  autohost.set('list', [
    { _id: 1, name: 'autohost-target-1', display_name: 'autohost-target-1' },
    { _id: 2, name: 'autohost-target-2', display_name: 'autohost-target-2' },
    { _id: 3, name: 'autohost-target-3', display_name: 'autohost-target-3' }
  ]);

  this.render(hbs`{{autohost-settings}}`);

  return wait().then(() => {
    assert.equal(this.ui.targets().length, 3, 'channels there');
    assert.equal(this.ui.moveUpButton().length, 3, 'move up buttons are there');
    assert.equal(this.ui.moveDownButton().length, 3, 'move down buttons are there');
    this.ui.moveUpButton()[1].click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.targets().length, 3, 'channels still there');
    assert.equal(this.ui.moveUpButton().length, 3, 'move up buttons are still there');
    assert.equal(this.ui.moveDownButton().length, 3, 'move down buttons are still there');
    assert.elementText(this.ui.targets()[0], 'autohost-target-2');
    assert.elementText(this.ui.targets()[1], 'autohost-target-1');
    this.ui.moveDownButton()[1].click();
    return wait();
  }).then(() => {
    assert.equal(this.ui.targets().length, 3, 'channels still there');
    assert.equal(this.ui.moveUpButton().length, 3, 'move up buttons are still there');
    assert.equal(this.ui.moveDownButton().length, 3, 'move down buttons are still there');
    assert.elementText(this.ui.targets()[1], 'autohost-target-3');
    assert.elementText(this.ui.targets()[2], 'autohost-target-1');
    return wait();
  });
});
