'use strict';

// Module dependencies
const Application = require('../Application');
const utils = require('../utils');
const chalk = require('chalk');

// Constants
const logPrefix = chalk.blue.bold('  baiji:evaluator');

// Evaluator Plugin
module.exports = function evaluatorPlugin(app, options) {
  if (process.env.NODE_ENV === 'production') {
    utils.logWarning('evaluator plugin should not be used in production!');
  }

  options = options || {};
  let warningThreshold = options.warningThreshold || 20;

  function injectEvaluator(defaultName) {
    return function(hook) {
      return function(ctx, next) {
        let startedAt = +new Date();
        return hook(ctx, function() {
          let millis = +new Date() - startedAt;
          let name = (hook.name).replace(/^bound\ /, '').trim();
          name = name || defaultName || '<anonymous>';
          let message = `${name} TIME COMSUMPTION: +${millis} ms`;
          if (millis >= warningThreshold) {
            // eslint-disable-next-line no-console
            console.log(logPrefix, chalk.red(message));
          } else {
            // eslint-disable-next-line no-console
            console.log(logPrefix, chalk.green(message));
          }
          return next();
        });
      };
    };
  }

  // Hack composedMethods
  Application.prototype.composedMethods = function() {
    let beforeHooks = this.searchHooksByType('before');
    let afterHooks = this.searchHooksByType('after');
    let afterErrorHooks = this.searchHooksByType('afterError');

    let filter = utils.filterHooks;

    return this.allMethods().map((method) => {
      let name = method.fullName();

      let beforeStack = filter(beforeHooks, name).map(injectEvaluator());
      let afterStack = filter(afterHooks, name).map(injectEvaluator());
      let afterErrorStack = filter(afterErrorHooks, name).map(injectEvaluator());

      method.fn = injectEvaluator(name)(method.fn);

      method.compose(
        beforeStack,
        afterStack,
        afterErrorStack
      );

      return method;
    });
  };
};

'use strict';

// Module dependencies
const Application = require('../Application');
const utils = require('../utils');
const chalk = require('chalk');

// Constants
const logPrefix = chalk.blue.bold('  baiji:evaluator');

// Evaluator Plugin
module.exports = function evaluatorPlugin(app, options) {
  if (process.env.NODE_ENV === 'production') {
    utils.logWarning('evaluator plugin should not be used in production!');
  }

  options = options || {};
  let warningThreshold = options.warningThreshold || 20;

  function injectEvaluator(defaultName) {
    return function(fn) {

      return function(ctx, next) {
        let startedAt = +new Date();

        return fn(ctx, function() {
          let millis = +new Date() - startedAt;

          let name = (fn.name).replace(/^bound\ /, '').trim();
          name = name || defaultName || '<anonymous>';

          let message = `${name} TIME COMSUMPTION: +${millis} ms`;

          if (millis >= warningThreshold) {
            // eslint-disable-next-line no-console
            console.log(logPrefix, chalk.red(message));
          } else {
            // eslint-disable-next-line no-console
            console.log(logPrefix, chalk.green(message));
          }
          return next();
        });
      };
    };
  }

  // Hack composedMethods
  Application.prototype.composedMethods = function() {
    let beforeHooks = this.searchHooksByType('before');
    let afterHooks = this.searchHooksByType('after');
    let afterErrorHooks = this.searchHooksByType('afterError');

    let filter = utils.filterHooks;

    // Loop and then inject evaluator into all methods and hooks
    return this.allMethods().map((method) => {
      let name = method.fullName();

      let beforeStack = filter(beforeHooks, name).map(injectEvaluator());
      let afterStack = filter(afterHooks, name).map(injectEvaluator());
      let afterErrorStack = filter(afterErrorHooks, name).map(injectEvaluator());

      method.fn = injectEvaluator(name)(method.fn);

      method.compose(
        beforeStack,
        afterStack,
        afterErrorStack
      );

      return method;
    });
  };
};

add more comments