/* globals Twitch */
import moduleForComponent from 'web-client/tests/helpers/module-for-component';
import { test } from 'qunit';
import hbs from 'htmlbars-inline-precompile';
import wait from 'ember-test-helpers/wait';
import { stubLogin } from 'web-client/tests/helpers/stub-login';
import videoScenario from 'web-client/mirage/scenarios/video';

moduleForComponent('Integration | manager/download-link', {
  beforeEach() {
    stubLogin({ chat_oauth_token: 'oauth-token' });

    this.video = videoScenario(this.server);
    this.set('videoId', this.video.id);

    this.tasks = [];
    this.set('runTask', (fn) => {
      this.tasks.push(fn);
    });

    // Ensure that that Twitch.user is loaded by the time the tests start.
    // This works around an issue where api.authRequest will not wait for
    // the user to load.
    return Twitch.user();
  }
});

test("Normal download workflow", function(assert) {
  assert.expect(8);

  this.render(hbs`{{manager/download-link videoId=videoId runTask=runTask}}`);

  assert.equal(this.$('a').text().trim(), 'Download', 'shows Download on init');

  this.$('a').click();

  assert.equal(this.$('a').text().trim(), 'Preparing…', 'shows Preparing after click');
  assert.equal(this.tasks.length, 0, 'there are no queued tasks');

  return wait().then(() => {
    assert.equal(this.$('a').text().trim(), 'Preparing…', 'continues to show Preparing after first request');
    assert.equal(this.tasks.length, 1, 'there is one queued task to make the next polling request');

    // The video becomes complete and we poll the server again
    this.video.reload().videoDownload.update('status', 'complete');
    this.tasks.shift()();

    return wait();
  }).then(() => {
    assert.equal(this.$('a').text().trim(), 'Begin Download', 'says Begin download once file is ready');
    assert.equal(this.$('a').attr('href'), this.video.videoDownload.download_url, 'href points to the file');
    assert.equal(this.tasks.length, 0, 'does not enqueue a task');
  });
});

test("Downloading and receiving a server error", function(assert) {
  assert.expect(3);

  this.server.get(
    'http://api.twitch.tv/kraken/vods/:videoId/download',
    { message: 'error-message' },
    401
  );

  this.render(hbs`{{manager/download-link videoId=videoId}}`);

  this.$('a').click();

  return wait().then(() => {
    assert.equal(this.$('a').text().trim(), 'Error', 'shows Error');
    assert.equal(this.$('[data-test-long-message]').text().trim(), 'error-message', 'shows error message');
    assert.equal(this.tasks.length, 0, 'does not enqueue a task');
  });
});

test("Downloading and getting failed status", function(assert) {
  assert.expect(3);

  this.render(hbs`{{manager/download-link videoId=videoId runTask=runTask}}`);

  this.$('a').click();

  return wait().then(() => {
    assert.equal(this.tasks.length, 1, 'there is one queued task to make the next polling request');

    // The video becomes "failed" and we poll the server again
    this.video.reload().videoDownload.update('status', 'failed');
    this.tasks.shift()();

    return wait();
  }).then(() => {
    assert.equal(this.$('a').text().trim(), 'Failed', 'says we failed');
    assert.equal(this.tasks.length, 0, 'does not enqueue a task');
  });
});

test("rate limited", function(assert) {
  this.owner.lookup('service:video-downloader').set('downloadLimit', 0);
  this.render(hbs`
    {{manager/download-link}}
  `);

  this.$('a').click();
  assert.equal(this.$('a').eq(0).text().trim(), 'Error');
});
