import { module, test } from 'qunit';
import { TimeSeries, parseTimeSeriesData } from 'web-client/utilities/video-stats/time-series';
import { StatsPoint } from 'web-client/utilities/video-stats/stats-point';
import { StatsNode } from 'web-client/utilities/video-stats/stats-node';
import { getTimeSeriesData } from 'web-client/mirage/fixtures/video-stats-timeseries';
import { AGGREGATION_DAILY } from 'web-client/models/video-stats/channel-timeseries';

const POINT_TIME = new Date(1991, 3, 7);
const NODE = new StatsNode('foo', 34);
const NESTED_NODE = new StatsNode('bar', 23);
const POINT = new StatsPoint(POINT_TIME);

POINT.setChildNodeFor([''], NODE);
POINT.setChildNodeFor(['foo'], NESTED_NODE);

module('Unit | Utils | video-stats/time-series', {
  beforeEach() {
    this.subject = new TimeSeries();
  }
});

test('getters', function(assert) {
  assert.deepEqual(this.subject.points, [], 'should retrieve points');
});

test('addPoint', function(assert) {
  let expectedPoint = new StatsPoint();
  this.subject.addPoint(expectedPoint);

  assert.equal(this.subject._points[0], expectedPoint, 'should properly add a new point');
});

test('getPoint', function(assert) {
  let expectedPoint = new StatsPoint(new Date(1991, 3, 6).toString());
  this.subject.addPoint(expectedPoint);

  assert.equal(this.subject.getPoint(expectedPoint.timeStamp), expectedPoint, 'should retrieve the specified point');
});

test('setPoints', function(assert) {
  let newPoints = [new StatsPoint()];
  this.subject.setPoints(newPoints);

  assert.equal(this.subject._points, newPoints, 'should replace the existing points');
});

test('listChildNodeLabelsFor', function(assert) {
  this.subject.addPoint(POINT);

  assert.deepEqual(this.subject.listChildNodeLabelsFor([NODE.label]), [NESTED_NODE.label], 'should return a list of the child node values at the specified level');
});

test('listChildNodeLabelsFor when there are no data points', function(assert) {
  assert.deepEqual(this.subject.listChildNodeLabelsFor(''), [], 'should return an empty array');
});

test("listChildNodeLabelsFor when the parent doesn't exist", function(assert) {
  assert.deepEqual(this.subject.listChildNodeLabelsFor(['bad', 'selector']), [], 'should return an empty array');
});

test('parseTimeSeriesData', function(assert) {
  assert.ok(parseTimeSeriesData(getTimeSeriesData()), 'should succesfully parse the data');
});

test('query without filter', function(assert) {
  let timeSeries = parseTimeSeriesData(getTimeSeriesData())[AGGREGATION_DAILY];

  let query = timeSeries.query({
    startTime: new Date(2016, 8, 18),
    endTime: new Date(2016, 8, 21),
    metric: 'viewcount',
    respectTimeZones: false
  });

  assert.equal(query[0].key, 'viewcount', 'returns an array with 1 item with key');

  let dataset = query[0];

  assert.equal(dataset.items.length, 4, 'should return the correct number of points');
  assert.equal(dataset.sum, 81507, 'sums the items in the dataset');
});

test('query with filter', function(assert) {
  let timeSeries = parseTimeSeriesData(getTimeSeriesData())[AGGREGATION_DAILY];

  let results = timeSeries.query({
    startTime: new Date(2016, 8, 18),
    endTime: new Date(2016, 8, 21),
    filter: { key: 'country', limit: 2 },
    metric: 'viewcount',
    respectTimeZones: false
  });

  assert.equal(results.length, 2, 'returns an array with top countries up to the limit');

  let usDataset = results[0];

  assert.equal(usDataset.key, 'US', 'is US dataset');
  assert.equal(usDataset.items.length, 4, 'selects 4 items');
  assert.equal(usDataset.sum, 29512, 'sums the items in the dataset');
});

test('query empty timeSeries without filter', function(assert) {
  let query = this.subject.query({
    startTime: new Date(2016, 8, 18),
    endTime: new Date(2016, 8, 21),
    metric: 'viewcount'
  });

  assert.deepEqual(query, [{ items: [], key: 'viewcount', sum: 0 }], 'returns an empty response for the metric');
});

test('query empty timeSeries with filter', function(assert) {
  let query = this.subject.query({
    startTime: new Date(2016, 8, 18),
    endTime: new Date(2016, 8, 21),
    filter: { key: 'country', limit: 2 },
    metric: 'viewcount'
  });

  assert.deepEqual(query, [], 'returns an empty response');
});

test('query with respectTimeZones true', function(assert) {
  let timeSeries = parseTimeSeriesData(getTimeSeriesData())[AGGREGATION_DAILY];

  let query = timeSeries.query({
    startTime: new Date('2016-09-18T00:00:00-07:00'),
    endTime: new Date('2016-09-21T00:00:00-07:00'),
    metric: 'viewcount',
    respectTimeZones: true
  });

  assert.equal(query[0].key, 'viewcount', 'returns an array with 1 item with key');

  let dataset = query[0];

  assert.equal(dataset.items.length, 3, 'should be 8/19-8/21 accounting for UTC offset');
  assert.equal(dataset.sum, 60557, 'sums the items in the dataset');
});
