var db = require('../../server/services/db');
var eventsDal = require('../../server/api/events/dal');
var getPoints = require('../../client/js/components/lib/getPoints');

exports.sumPoints = function (evs) {
  // Return sum of points of given events.
  return evs.reduce(function (acc, ev) {
    return acc + getPoints(ev);
  }, 0);
};

exports.computePoints = function (username, callback) {
  // Compute scenepoints for single user. Scenepoints are computed
  // from events.

  eventsDal.getAllOfUser(username, function (err, evs) {
    if (err) {
      return callback(err);
    }

    var points = exports.sumPoints(evs);
    var typerr;

    // Assert
    if (typeof points !== 'number' || isNaN(points)) {
      typerr = new Error('Invalid scene points sum: ' + points);
      return callback(typerr);
    }

    return callback(null, points);
  });
};

exports.computePointsAndStore = function (username, callback) {
  // Parameters:
  //   username
  //   callback
  //     function (err, points)
  exports.computePoints(username, function (err, points) {
    if (err) {
      return callback(err);
    }

    var coll = db.get().collection('users');

    var q = { name: username };
    var u = {
      $set: {
        points: points,
      },
    };

    coll.updateOne(q, u, function (err2) {
      if (err2) {
        return callback(err2);
      }

      return callback(null, points);
    });
  });
};

@@ -588,99 +588,970 @@
     
-var points = exports.sumPoints(evs);%0A    var typerr;%0A%0A    // Assert%0A    if (typeof points !
+// Compute UNIX timestamp and ensure order.%0A    var evsTimeUnix = evs.map(function (ev) %7B%0A      return Object.assign(%7B%7D, ev, %7B%0A        timeUnix: new Date(ev.time),%0A      %7D);%0A    %7D).sort(function (eva, evb) %7B%0A      return eva.timeUnix - evb.timeUnix;%0A    %7D);%0A%0A    // Event time frames%0A    var d30 = 30 * 24 * 60 * 60 * 1000; // eslint-disable-line no-magic-numbers%0A    var d7 = 7 * 24 * 60 * 60 * 1000; // eslint-disable-line no-magic-numbers%0A    var unix30daysAgo = Date.now() - d30;%0A    var unix7daysAgo = Date.now() - d7;%0A    var evs30days = evsTimeUnix.filter(function (ev) %7B%0A      return ev.timeUnix %3E unix30daysAgo;%0A    %7D);%0A    var evs7days = evsTimeUnix.filter(function (ev) %7B%0A      return ev.timeUnix %3E unix7daysAgo;%0A    %7D);%0A%0A    // Point Categories%0A    var ps = %7B%0A      allTime: exports.sumPoints(evs),%0A      days30: exports.sumPoints(evs30days),%0A      days7: exports.sumPoints(evs7days),%0A    %7D;%0A%0A    var isOk = function (num) %7B%0A      return typeof num =
 == '
@@ -1562,23 +1562,125 @@
 er' 
-%7C%7C 
+&& !
 isNaN(
-points
+num);%0A    %7D;%0A%0A    // Assert%0A    var typerr;%0A    if (!isOk(ps.allTime) %7C%7C !isOk(ps.days30) %7C%7C !isOk(ps.days7
 )) %7B
@@ -1736,22 +1736,34 @@
 um: ' + 
-points
+JSON.stringify(ps)
 );%0A     
@@ -1818,28 +1818,24 @@
 back(null, p
-oint
 s);%0A  %7D);%0A%7D;
@@ -1896,24 +1896,29 @@
 callback) %7B%0A
+  //%0A
   // Paramet
@@ -1976,25 +1976,22 @@
 ion (err
-, points)
+)%0A  //
 %0A  expor
@@ -2037,16 +2037,25 @@
 r, point
+Categorie
 s) %7B%0A   
@@ -2228,17 +2228,124 @@
 s: point
-s
+Categories.allTime,%0A        points30days: pointCategories.days30,%0A        points7days: pointCategories.days7
 ,%0A      
@@ -2486,16 +2486,8 @@
 null
-, points
 );%0A 

Worker computes 7 days and 30 days totals