text: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  'use strict';
  
  const _ = require('lodash');
  
  // Fire me up!
  
  module.exports = {
      implements: 'services/activities',
      inject: ['mongo']
  };
  
  /**
   * @param mongo
   * @returns {ActivitiesService}
   */
  module.exports.factory = (mongo) => {
      class ActivitiesService {
          /**
           * Update page activities.
           *
           * @param {String} owner - User ID
           * @param {String} action - Action string presentation.
           * @param {String} group - Action group string presentation.
           * @param {Date} [now] - Optional date to save in activity.
           * @returns {Promise.<mongo.ObjectId>} that resolve activity
           */
          static merge(owner, {action, group}, now = new Date()) {
              mongo.Account.findById(owner)
                  .then((user) => {
                      user.lastActivity = new Date();
  
                      return user.save();
                  });
  
              const date = Date.UTC(now.getFullYear(), now.getMonth(), 1);
  
              return mongo.Activities.findOneAndUpdate({owner, action, date},
                  {$set: {owner, group, action, date}, $inc: {amount: 1}}, {new: true, upsert: true}).exec();
          }
  
          static total({startDate, endDate}) {
              const $match = {};
  
              if (startDate)
                  $match.date = {$gte: new Date(startDate)};
  
              if (endDate) {
                  $match.date = $match.date || {};
                  $match.date.$lt = new Date(endDate);
              }
  
              return mongo.Activities.aggregate([
                  {$match},
                  {$group: {
                      _id: {owner: '$owner', group: '$group'},
                      amount: {$sum: '$amount'}
                  }}
              ]).exec().then((data) => {
                  return _.reduce(data, (acc, { _id, amount }) => {
                      const {owner, group} = _id;
                      acc[owner] = _.merge(acc[owner] || {}, { [group]: amount });
                      return acc;
                  }, {});
              });
          }
  
          static detail({startDate, endDate}) {
              const $match = { };
  
              if (startDate)
                  $match.date = {$gte: new Date(startDate)};
  
              if (endDate) {
                  $match.date = $match.date || {};
                  $match.date.$lt = new Date(endDate);
              }
  
              return mongo.Activities.aggregate([
                  {$match},
                  {$group: {_id: {owner: '$owner', action: '$action'}, total: {$sum: '$amount'}}}
              ]).exec().then((data) => {
                  return _.reduce(data, (acc, { _id, total }) => {
                      const {owner, action} = _id;
                      acc[owner] = _.merge(acc[owner] || {}, { [action]: total });
                      return acc;
                  }, {});
              });
          }
      }
  
      return ActivitiesService;
  };
  