import moduleForComponent from 'web-client/tests/helpers/module-for-component';
import { test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Object from 'ember-object';
import wait from 'ember-test-helpers/wait';

import { MAX_TITLE_LENGTH } from 'web-client/components/dashboards/live/edit-broadcast/component';

moduleForComponent('dashboards/live/edit-broadcast', 'Integration | Component | dashboards/live/edit-broadcast');

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

  let channel = Object.create();

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.equal(this.$('[data-test-selector="title"] input').attr('value'), '', 'title is NOT set by default');

  assert.equal(
    this.$('[data-test-selector="language"] select').attr('value'),
    'Pick a Language',
    'language is NOT selected by default'
  );

  assert.ok(
    this.$('[data-test-selector="language"] select option:selected').prop('disabled'),
    'placeholder option is disabled'
  );

  assert.equal(
    this.$('[data-test-selector="game"] input').attr('value'),
    '',
    'game is NOT set by default'
  );

  assert.elementText(this.$('button.button'), 'Update Information', 'button has text');
});

test('title validation', function(assert) {
  assert.expect(12);

  let title = 'Test Stream Title!';
  let longTitle = Array(MAX_TITLE_LENGTH * 2).join('*');
  let channel = Object.create({ broadcasterLanguage: 'en' });

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.notOk(this.$('[data-test-selector="title"] input').attr('value'), 'title is NOT set by default');

  assert.stringIncludes(
    this.$('[data-test-selector="title"] .form__hint').text(),
    MAX_TITLE_LENGTH,
    'number of characters remain unused is rendered'
  );

  this.set('channel.status', title);

  assert.equal(this.$('[data-test-selector="title"] input').attr('value'), title, 'title is set');

  assert.stringIncludes(
    this.$('[data-test-selector="title"] .form__hint').text(),
    MAX_TITLE_LENGTH - title.length,
    'number of characters remain unused is rendered'
  );

  assert.notOk(this.$('button.button').prop('disabled'), 'button is NOT disabled');
  assert.notOk(this.$('button.button').hasClass('button--disabled'), 'button does NOT have the disabled class');

  this.set('channel.status', longTitle);

  assert.equal(this.$('[data-test-selector="title"] input').attr('value'), longTitle, 'title is set');

  assert.ok(
    this.$('[data-test-selector="title"]').hasClass('form__group--error'),
    'form group shows error state'
  );

  assert.stringIncludes(
    this.$('[data-test-selector="title"] .form__hint').text(),
    MAX_TITLE_LENGTH - longTitle.length,
    'number of characters remain unused is rendered'
  );

  assert.ok(
    this.$('[data-test-selector="title"] .form__hint').hasClass('form__hint--error'),
    'form hint shows error state'
  );

  assert.ok(this.$('button.button').prop('disabled'), 'button is disabled');
  assert.ok(this.$('button.button').hasClass('button--disabled'), 'button has the disabled class');
});

test('broadcast language validation', function(assert) {
  assert.expect(7);

  let broadcasterLanguage = 'en';
  let channel = Object.create();

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.equal(
    this.$('[data-test-selector="language"] select').attr('value'),
    'Pick a Language',
    'language is NOT selected by default and the placeholder option is selected'
  );

  assert.ok(
    this.$('[data-test-selector="language"] select option:selected').prop('disabled'),
    'placeholder option is disabled to prevent selecting'
  );

  assert.ok(this.$('button.button').prop('disabled'), 'button is disabled as a broadcaster language is required');
  assert.ok(this.$('button.button').hasClass('button--disabled'), 'button has the disabled class');

  this.set('channel.broadcasterLanguage', broadcasterLanguage);

  assert.equal(
    this.$('[data-test-selector="language"] select').attr('value'),
    broadcasterLanguage,
    'English is selected'
  );

  assert.notOk(this.$('button.button').prop('disabled'), 'button is NOT disabled');
  assert.notOk(this.$('button.button').hasClass('button--disabled'), 'button does NOT have the disabled class');
});

test('disables chat language restriction when selecting the broadcast language "Other"', function(assert) {
  assert.expect(5);

  let channel = Object.create();

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.notOk(
    this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').prop('checked'),
    'chat language restriction checkbox is NOT checked by default'
  );

  assert.notOk(
    this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').prop('disabled'),
    'chat language restriction checkbox is NOT disabled by default'
  );

  this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').click();

  assert.ok(
    this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').prop('checked'),
    'chat language restriction checkbox is checked'
  );

  this.$('[data-test-selector="language"] select').val('other').change();

  assert.notOk(
    this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').prop('checked'),
    'chat language restriction checkbox is NOT checked'
  );

  assert.ok(
    this.$('[data-test-selector="chat-language-restriction"] input[type="checkbox"]').prop('disabled'),
    'chat language restriction checkbox is disabled'
  );
});


test('game validation', function(assert) {
  assert.expect(15);

  let done = assert.async();
  let channel = Object.create({ broadcasterLanguage: 'en' });

  this.server.create('game', { name: 'Fake Game II', _id: 1 });

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.equal(
    this.$('[data-test-selector="game"] input').attr('value'),
    '',
    'game is empty by default'
  );

  assert.elementText(this.$('[data-test-selector="game"] .form__label'), 'Not Playing', 'label shows "Not Playing"');

  assert.notOk(
    this.$('[data-test-selector="game"]').hasClass('form__group--error'),
    'form group is NOT in error state'
  );

  assert.elementCount(
    this.$('[data-test-selector="game"] p.form__hint.form__hint--error'),
    0,
    'form hint error is NOT rendered'
  );

  assert.notOk(this.$('button.button').prop('disabled'), 'button is NOT disabled');
  assert.notOk(this.$('button.button').hasClass('button--disabled'), 'button does NOT have the disabled class');

  this.$('[data-test-selector="game"] input').val('Not a real game!!1').trigger('input');

  return wait().then(() => {
    assert.ok(this.$('[data-test-selector="game"]').hasClass('form__group--error'), 'form group is in error state');

    assert.elementText(
      this.$('[data-test-selector="game"] p.form__hint.form__hint--error'),
      'Please choose a supported game',
      'form hint error is rendered'
    );

    assert.ok(this.$('button.button').prop('disabled'), 'button is disabled');
    assert.ok(this.$('button.button').hasClass('button--disabled'), 'button has the disabled class');

    this.$('[data-test-selector="game"] input').val('Fake Game II').trigger('input');

    return wait();
  }).then(() => {
    assert.notOk(
      this.$('[data-test-selector="game"]').hasClass('form__group--error'),
      'form group is NOT in error state'
    );

    assert.elementText(this.$('[data-test-selector="game"] .form__label'), 'Playing', 'label shows "Playing"');

    assert.elementCount(
      this.$('[data-test-selector="game"] p.form__hint.form__hint--error'),
      0,
      'form hint error is NOT rendered'
    );

    assert.notOk(this.$('button.button').prop('disabled'), 'button is once again NOT disabled');
    assert.notOk(this.$('button.button').hasClass('button--disabled'), 'button does NOT have the disabled class');

    return done();
  });
});

test('selecting "Programming" or "Game Development" games', function(assert) {
  assert.expect(7);

  let done = assert.async();
  let channel = Object.create();

  this.server.create('game', { name: 'Programming', _id: 1 });
  this.server.create('game', { name: 'Game Development', _id: 2 });
  this.server.create('game', { name: 'Creative', _id: 3 });

  this.set('channel', channel);

  this.render(hbs`{{dashboards/live/edit-broadcast channel=channel}}`);

  assert.equal(this.$('[data-test-selector="title"] input').attr('value'), '', 'title is empty by default');

  assert.equal(
    this.$('[data-test-selector="game"] input').attr('value'),
    '',
    'game is empty by default'
  );

  this.$('[data-test-selector="game"] input').val('Programming').trigger('input');

  return wait().then(() => {
    assert.equal(
      this.$('[data-test-selector="title"] input').attr('value'),
      '#programming',
      'title has "#programming" hashtag without a leading space character'
    );

    assert.equal(
      this.$('[data-test-selector="game"] input').attr('value'),
      'Creative',
      'game is changed to "Creative"'
    );

    this.$('[data-test-selector="game"] input').val('').trigger('input');

    return wait();
  }).then(() => {
    this.$('[data-test-selector="title"] input').val('Not programming!!').trigger('input');
    this.$('[data-test-selector="game"] input').val('Game Development').trigger('input');

    return wait();
  }).then(() => {
    assert.equal(
      this.$('[data-test-selector="title"] input').attr('value'),
      'Not programming!! #gamedev',
      'title has "#gamedev" hashtag appended with a space character for separation'
    );

    assert.equal(
      this.$('[data-test-selector="game"] input').attr('value'),
      'Creative',
      'game is once again changed to "Creative"'
    );

    this.$('[data-test-selector="title"] input').val('Definitely programming! #programming').trigger('input');
    this.$('[data-test-selector="game"] input').val('').trigger('input').trigger('input');
    this.$('[data-test-selector="game"] input').val('Programming').trigger('input').trigger('input');

    return wait();
  }).then(() => {
    let title = this.$('[data-test-selector="title"] input').attr('value');
    let hashtagMatches = title.match(/\#programming/g) || [];

    assert.equal(hashtagMatches.length, 1, 'hashtag is NOT appended again if it is already present in the title');

    return done();
  });
});
