'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;
    });
  };
};

@@ -573,16 +573,15 @@
 ion(
-hook
+fn
 ) %7B%0A
+%0A
     
@@ -644,24 +644,25 @@
 new Date();%0A
+%0A
         retu
@@ -664,20 +664,18 @@
  return 
-hook
+fn
 (ctx, fu
@@ -733,16 +733,17 @@
 rtedAt;%0A
+%0A
         
@@ -760,12 +760,10 @@
  = (
-hook
+fn
 .nam
@@ -852,16 +852,17 @@
 mous%3E';%0A
+%0A
         
@@ -920,16 +920,17 @@
 s%7D ms%60;%0A
+%0A
         
@@ -1563,16 +1563,81 @@
 Hooks;%0A%0A
+    // Loop and then inject evaluator into all methods and hooks%0A
     retu

add more comments