'use strict';

var _ = require('lodash');

var _customErrors = [];

exports.registerError = (name, statusCode, messageTemplate) => {
  _validate(name);
  name = _.upperFirst(name);
  var CustomError = _createCustomError(name, statusCode);
  _createFunctions(name, CustomError, messageTemplate);

  _customErrors.push({
    name,
    type: CustomError
  });
};

exports.isKnownError = (err) => {
  return _.some(_customErrors, custErr => err instanceof custErr.type || err === custErr.name);
};

function _validate(name) {
  if (!name) {
    throw new Error('Custom error name is required');
  }
  if (_.some(_customErrors, { name })) {
    throw new Error(`Custom error ${name} is already registered`);
  }
}

function _createCustomError(name, statusCode) {
  var CustomError = function(msg) {
    this.name = name + 'Error';
    this.message = msg;
    this.statusCode = statusCode;
  };
  CustomError.prototype = new Error();

  return CustomError;
}

function _createFunctions(name, CustomError, messageTemplate) {
  exports[`is${name}Error`] = function(err) {
    return err instanceof CustomError;
  };

  exports[`get${name}Error`] = function(msg) {
    if (messageTemplate && !_.isString(msg) && _.isObject(msg)) {
      var msgParams = msg;
      msg = _.reduce(msgParams, (result, paramVal, paramKey) => {
        result = _.replace(result, '${' + paramKey + '}', paramVal);
        return result;
      }, messageTemplate);
    }
    return new CustomError(msg);
  };

  exports[`rejectWith${name}Error`] = function(msg) {
    var err = exports[`get${name}Error`](msg);
    return Promise.reject(err);
  };
}

@@ -1045,34 +1045,16 @@
 %5D = 
-function(err) %7B%0A    return
+(err) =%3E
  err
@@ -1078,19 +1078,69 @@
 mError;%0A
+%0A
   
-%7D
+exports%5B%60get$%7Bname%7DErrorType%60%5D = () =%3E CustomError
 ;%0A%0A  exp
@@ -1161,37 +1161,32 @@
 e%7DError%60%5D = 
-function
 (msg)
+ =%3E
  %7B%0A    if (m
@@ -1537,29 +1537,24 @@
 ror%60%5D = 
-function
 (msg)
+ =%3E
  %7B%0A    v

add get<Error>Type helper function, use arrow functions