text: 'use strict';
  
  const test = require('ava');
  const moment = require('moment');
  const lolex = require('lolex');
  
  const { EventEmitter } = require('events');
  const UnleashClientMetrics = require('./index');
  
  const appName = 'appName';
  const instanceId = 'instanceId';
  
  test('should work without state', t => {
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
  
      t.truthy(metrics.getAppsWithToggles());
      t.truthy(metrics.getTogglesMetrics());
  
      metrics.destroy();
  });
  
  test.cb('data should expire', t => {
      const clock = lolex.install();
  
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
  
      metrics.addPayload({
          appName,
          instanceId,
          bucket: {
              start: Date.now() - 2000,
              stop: Date.now() - 1000,
              toggles: {
                  toggleX: {
                      yes: 123,
                      no: 0,
                  },
              },
          },
      });
  
      let lastHourExpires = 0;
      metrics.lastHourList.on('expire', () => {
          lastHourExpires++;
      });
  
      let lastMinExpires = 0;
      metrics.lastMinuteList.on('expire', () => {
          lastMinExpires++;
      });
  
      clock.tick(60 * 1000);
      t.true(lastMinExpires === 1);
      t.true(lastHourExpires === 0);
  
      clock.tick(60 * 60 * 1000);
      t.true(lastMinExpires === 1);
      t.true(lastHourExpires === 1);
  
      clock.uninstall();
      t.end();
  });
  
  test('should listen to metrics from store', t => {
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
      store.emit('metrics', {
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: {
                  toggleX: {
                      yes: 123,
                      no: 0,
                  },
              },
          },
      });
  
      t.truthy(metrics.apps[appName].count === 123);
      t.truthy(metrics.globalCount === 123);
  
      t.deepEqual(metrics.getTogglesMetrics().lastHour.toggleX, {
          yes: 123,
          no: 0,
      });
      t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
          yes: 123,
          no: 0,
      });
  
      metrics.addPayload({
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: {
                  toggleX: {
                      yes: 10,
                      no: 10,
                  },
              },
          },
      });
  
      t.truthy(metrics.globalCount === 143);
      t.deepEqual(metrics.getTogglesMetrics().lastHour.toggleX, {
          yes: 133,
          no: 10,
      });
      t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
          yes: 133,
          no: 10,
      });
  
      metrics.destroy();
  });
  
  test('should build up list of seend toggles when new metrics arrives', t => {
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
      store.emit('metrics', {
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: {
                  toggleX: {
                      yes: 123,
                      no: 0,
                  },
                  toggleY: {
                      yes: 50,
                      no: 50,
                  },
              },
          },
      });
  
      const appToggles = metrics.getAppsWithToggles();
      const togglesForApp = metrics.getSeenTogglesByAppName(appName);
  
      t.truthy(appToggles.length === 1);
      t.truthy(appToggles[0].seenToggles.length === 2);
      t.truthy(appToggles[0].seenToggles.includes('toggleX'));
      t.truthy(appToggles[0].seenToggles.includes('toggleY'));
  
      t.truthy(togglesForApp.length === 2);
      t.truthy(togglesForApp.includes('toggleX'));
      t.truthy(togglesForApp.includes('toggleY'));
      metrics.destroy();
  });
  
  test('should handle a lot of toggles', t => {
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
  
      const toggleCounts = {};
      for (let i = 0; i < 100; i++) {
          toggleCounts[`toggle${i}`] = { yes: i, no: i };
      }
  
      store.emit('metrics', {
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: toggleCounts,
          },
      });
  
      const seenToggles = metrics.getSeenTogglesByAppName(appName);
  
      t.truthy(seenToggles.length === 100);
      metrics.destroy();
  });
  
  test('should have correct values for lastMinute', t => {
      const clock = lolex.install();
  
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
  
      const now = new Date();
      const input = [
          {
              start: moment(now).subtract(1, 'hour'),
              stop: moment(now).subtract(59, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).subtract(30, 'minutes'),
              stop: moment(now).subtract(29, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).subtract(2, 'minutes'),
              stop: moment(now).subtract(1, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).subtract(2, 'minutes'),
              stop: moment(now).subtract(59, 'seconds'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now),
              stop: moment(now).subtract(30, 'seconds'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
      ];
  
      input.forEach(bucket => {
          store.emit('metrics', {
              appName,
              instanceId,
              bucket,
          });
      });
  
      const seenToggles = metrics.getSeenTogglesByAppName(appName);
      t.truthy(seenToggles.length === 1);
  
      // metrics.se
      let c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastMinute.toggle, { yes: 20, no: 20 });
  
      clock.tick(10 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastMinute.toggle, { yes: 10, no: 10 });
  
      clock.tick(20 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastMinute.toggle, { yes: 0, no: 0 });
  
      metrics.destroy();
      clock.uninstall();
  });
  
  test('should have correct values for lastHour', t => {
      const clock = lolex.install();
  
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
  
      const now = new Date();
      const input = [
          {
              start: moment(now).subtract(1, 'hour'),
              stop: moment(now).subtract(59, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).subtract(30, 'minutes'),
              stop: moment(now).subtract(29, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).subtract(15, 'minutes'),
              stop: moment(now).subtract(14, 'minutes'),
              toggles: {
                  toggle: { yes: 10, no: 10 },
              },
          },
          {
              start: moment(now).add(59, 'minutes'),
              stop: moment(now).add(1, 'hour'),
              toggles: {
                  toggle: { yes: 11, no: 11 },
              },
          },
      ];
  
      input.forEach(bucket => {
          store.emit('metrics', {
              appName,
              instanceId,
              bucket,
          });
      });
  
      const seenToggles = metrics.getSeenTogglesByAppName(appName);
  
      t.truthy(seenToggles.length === 1);
  
      // metrics.se
      let c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 41, no: 41 });
  
      clock.tick(10 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 41, no: 41 });
  
      // at 30
      clock.tick(30 * 60 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 31, no: 31 });
  
      // at 45
      clock.tick(15 * 60 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 21, no: 21 });
  
      // at 1:15
      clock.tick(30 * 60 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 11, no: 11 });
  
      // at 2:00
      clock.tick(45 * 60 * 1000);
      c = metrics.getTogglesMetrics();
      t.deepEqual(c.lastHour.toggle, { yes: 0, no: 0 });
  
      metrics.destroy();
      clock.uninstall();
  });
  
  test('should not fail when toggle metrics is missing yes/no field', t => {
      const store = new EventEmitter();
      const metrics = new UnleashClientMetrics(store);
      store.emit('metrics', {
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: {
                  toggleX: {
                      yes: 123,
                      no: 0,
                  },
              },
          },
      });
  
      metrics.addPayload({
          appName,
          instanceId,
          bucket: {
              start: new Date(),
              stop: new Date(),
              toggles: {
                  toggleX: {
                      blue: 10,
                      green: 10,
                  },
              },
          },
      });
  
      t.is(metrics.globalCount, 123);
      t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
          yes: 123,
          no: 0,
      });
  
      metrics.destroy();
  });
  