import { moduleForComponent, test } from 'ember-qunit';
import Service from 'ember-service';
import RSVP from 'rsvp';
import wait from 'ember-test-helpers/wait';
import { pollTaskFor } from 'web-client/mixins/context-bound-tasks';
import { DEFAULT_DASHBOARD_CONFIG, COMPONENT_PATHS } from 'web-client/components/dashboards/live/live-container/component';

moduleForComponent('dashboards/live/live-container', 'Unit | Component | dashboards/live/live-container', { unit: true });

test('uses default dashboard layout if none is found in localStorage', function(assert) {
  assert.expect(1);

  let storageServiceStub = Service.extend({
    dashboardConfiguration: undefined
  });

  let ingestServiceStub = Service.extend({
    getHealth() {
      return RSVP.resolve({
        health_code: 100,
        health_reason_codes: [1000]
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);
  this.register('service:storage', storageServiceStub);

  let container = this.subject();
  let dashboardConfig = container.get('dashboardConfig');
  let resultConfig = dashboardConfig.map(column => {
    return column.map(comp => COMPONENT_PATHS[comp.path]);
  });

  assert.deepEqual(resultConfig, DEFAULT_DASHBOARD_CONFIG, 'default dashboardConfig is used');
});

test('uses default dashboard layout if localStorage dashboardConfiguration is corrupted', function(assert) {
  assert.expect(1);

  let storageServiceStub = Service.extend({
    dashboardConfiguration: '[[{thisWillNotParse: }]'
  });

  let ingestServiceStub = Service.extend({
    getHealth() {
      return RSVP.resolve({
        health_code: 100,
        health_reason_codes: [1000]
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);
  this.register('service:storage', storageServiceStub);

  let container = this.subject();
  let dashboardConfig = container.get('dashboardConfig');
  let resultConfig = dashboardConfig.map(column => {
    return column.map(comp => COMPONENT_PATHS[comp.path]);
  });

  assert.deepEqual(resultConfig, DEFAULT_DASHBOARD_CONFIG, 'default dashboardConfig is used');
});

test('helper functions do convert class name to component properly', function(assert) {
  assert.expect(2);

  let ingestServiceStub = Service.extend({
    getHealth() {
      return RSVP.resolve({
        health_code: 100,
        health_reason_codes: [1000]
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);

  const container = this.subject();

  let convertedComponent = container._convertClassToComponent('js-dashboard-edit-broadcast');
  let resultComponent = {
    path: 'dashboards/live/edit-broadcast',
    isCollapsed: false
  };

  assert.deepEqual(convertedComponent, resultComponent, 'class correctly converted into component');

  let fakeComponent = container._convertClassToComponent('js-dashboard-fake-component');

  assert.deepEqual(fakeComponent, undefined, 'a fake component name returns null');
});

test('helper function appends correct data to component', function(assert) {
  assert.expect(2);

  let ingestServiceStub = Service.extend({
    getHealth() {
      return RSVP.resolve({
        health_code: 100,
        health_reason_codes: [1000]
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);

  const container = this.subject();

  let storedComponent = {
    path: 'dashboards/live/edit-broadcast',
    isCollapsed: false
  };

  let completeComponent = {
    path: 'dashboards/live/edit-broadcast',
    isCollapsed: false,
    name: 'Stream Information',
    partnerOnly: false,
    noPad: false,
    fullCol: false,
    hasSettings: false
  };

  assert.deepEqual(container._convertStorageToDashboardConfig(storedComponent), completeComponent, 'stored component has correct data appended');

  let fakeComponent = {
    path: 'dashboards/live/fake-component',
    isCollapsed: false
  };

  assert.deepEqual(container._convertStorageToDashboardConfig(fakeComponent), undefined, 'fake component returns null');
});

test('retrieves getHealth from ingest service, can determine isLive', function(assert) {
  assert.expect(4);

  let done = assert.async();

  let ingestServiceStub = Service.extend({
    getHealth() {
      assert.ok(true, 'ingest service is invoked to GET health');

      return RSVP.resolve({
        health_code: 100,
        health_reason_codes: [1000]
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);

  let container = this.subject();

  return wait().then(() => {
    assert.equal(container.get('isLive'), true, 'isLive is determined to be true');
    assert.equal(container.get('qualityCode'), 100, 'qualityCode is retrieved');
    assert.equal(container.get('reasonCodes')[0], 1000, 'reasonCodes are retrieved');

    done();
  });
});

test('retrieves getHealth from ingest service, can determine channel is offline', function(assert) {
  assert.expect(4);

  let done = assert.async();

  let ingestServiceStub = Service.extend({
    getHealth() {
      assert.ok(true, 'ingest service is invoked to GET health');

      return RSVP.reject({
        status: 404
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);

  let container = this.subject();

  return wait().then(() => {
    assert.equal(container.get('isLive'), false, 'isLive is determined to be false');
    assert.equal(container.get('qualityCode'), undefined, 'qualityCode is not retrieved');
    assert.equal(container.get('reasonCodes'), undefined, 'reasonCodes are not retrieved');

    done();
  });
});

test('retrieves getHealth from ingest service, channel goes from offline to online to offline', function(assert) {
  assert.expect(6);

  let done = assert.async();
  let online = false;

  let ingestServiceStub = Service.extend({
    getHealth() {
      assert.ok(true, 'ingest service is invoked to GET health');

      if (online) {
        return RSVP.resolve({
          health_code: 100,
          health_reason_codes: [1000]
        });
      }

      return RSVP.reject({
        status: 404
      });
    }
  });

  this.register('service:ingest', ingestServiceStub);

  let container = this.subject();

  return wait().then(() => {
    assert.equal(container.get('isLive'), false, 'isLive is determined to be false');

    online = true;

    pollTaskFor('live-container#update-quality');

    return wait();
  }).then(() => {
    assert.equal(container.get('isLive'), true, 'isLive is determined to be true, user went online');

    online = false;

    pollTaskFor('live-container#update-quality');

    return wait();
  }).then(() => {
    assert.equal(container.get('isLive'), false, 'isLive is determined to be false, user went offline');

    done();
  });
});
