
var statuses = require('statuses');
var inherits = require('inherits');

exports = module.exports = function httpError() {
  // so much arity going on ~_~
  var err;
  var msg;
  var status = 500;
  var props = {};
  for (var i = 0; i < arguments.length; i++) {
    var arg = arguments[i];
    if (arg instanceof Error) {
      err = arg;
      status = err.status || err.statusCode || status;
      continue;
    }
    switch (typeof arg) {
      case 'string':
        msg = arg;
        break;
      case 'number':
        status = arg;
        break;
      case 'object':
        props = arg;
        break;
    }
  }

  if (typeof status !== 'number' || !statuses[status]) status = 500;

  if (!err) {
    // create error
    err = new Error(msg || statuses[status])
    Error.captureStackTrace(err, httpError)
  }

  err.expose = status < 500;
  for (var key in props) err[key] = props[key];
  err.status = err.statusCode = status;
  return err;
};

// create generic error objects
var codes = statuses.codes.filter(function (num) {
  return num >= 400;
});

codes.forEach(function (code) {
  if (code >= 500) {
    var ServerError = function ServerError(msg) {
      var self = new Error(msg != null ? msg : statuses[code])
      Error.captureStackTrace(self, ServerError)
      self.__proto__ = ServerError.prototype
      return self
    }
    inherits(ServerError, Error);
    ServerError.prototype.status =
    ServerError.prototype.statusCode = code;
    ServerError.prototype.expose = false;
    exports[code] =
    exports[statuses[code].replace(/\s+/g, '')] = ServerError;
    return;
  }

  var ClientError = function ClientError(msg) {
    var self = new Error(msg != null ? msg : statuses[code])
    Error.captureStackTrace(self, ClientError)
    self.__proto__ = ClientError.prototype
    return self
  }
  inherits(ClientError, Error);
  ClientError.prototype.status =
  ClientError.prototype.statusCode = code;
  ClientError.prototype.expose = true;
  exports[code] =
  exports[statuses[code].replace(/\s+/g, '')] = ClientError;
  return;
});
