// Generated by CoffeeScript 1.9.3
(function() {
  var BunyanDebugStream, EXPRESS_BUNYAN_LOGGER_FIELDS, FIELDS_TO_IGNORE, LEVELS, Writable, applyColors, bunyan, colors, dateToString, exceptionFormatter, exports, isString, path, ref, ref1, serializer, serializerName, serializers, srcToString,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;

  path = require('path');

  Writable = require('stream').Writable;

  bunyan = require('bunyan');

  colors = require('colors/safe');

  exceptionFormatter = require('exception-formatter');

  ref = require('./utils'), srcToString = ref.srcToString, applyColors = ref.applyColors, dateToString = ref.dateToString, isString = ref.isString;

  LEVELS = (function() {
    var answer, o;
    answer = {};
    o = function(level, prefix, colors) {
      return answer[level] = {
        level: level,
        prefix: prefix,
        colors: colors
      };
    };
    o(bunyan.TRACE, 'TRACE:', ['grey']);
    o(bunyan.DEBUG, 'DEBUG:', ['cyan']);
    o(bunyan.INFO, 'INFO: ', ['green']);
    o(bunyan.WARN, 'WARN: ', ['yellow']);
    o(bunyan.ERROR, 'ERROR:', ['red']);
    o(bunyan.FATAL, 'FATAL:', ['magenta']);
    return answer;
  })();

  FIELDS_TO_IGNORE = ['src', 'msg', 'name', 'hostname', 'pid', 'level', 'time', 'v', 'err'];

  EXPRESS_BUNYAN_LOGGER_FIELDS = ['remote-address', 'ip', 'method', 'url', 'referer', 'user-agent', 'body', 'short-body', 'http-version', 'response-hrtime', 'status-code', 'req-headers', 'res-headers', 'incoming', 'req_id'];

  BunyanDebugStream = (function(superClass) {
    extend(BunyanDebugStream, superClass);

    function BunyanDebugStream(options1) {
      var c, key, level, levelName, levelValue, ref1, ref10, ref11, ref12, ref13, ref14, ref15, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, self, value;
      this.options = options1 != null ? options1 : {};
      BunyanDebugStream.__super__.constructor.call(this, {
        objectMode: true
      });
      if (this.options.forceColor) {
        colors.enabled = true;
      }
      this._colors = {};
      if (('colors' in this.options) && !this.options.colors) {
        this._useColor = false;
        for (levelValue in LEVELS) {
          level = LEVELS[levelValue];
          this._colors[levelValue] = [];
        }
      } else {
        this._useColor = true;
        for (levelValue in LEVELS) {
          level = LEVELS[levelValue];
          this._colors[levelValue] = level.colors;
        }
        ref2 = (ref1 = this.options.colors) != null ? ref1 : {};
        for (level in ref2) {
          c = ref2[level];
          if (isString(c)) {
            c = [c];
          }
          if (this._colors[level] != null) {
            this._colors[level] = c;
          } else {
            levelName = level;
            level = bunyan[levelName != null ? levelName.toUpperCase() : void 0];
            if (this._colors[level] != null) {
              this._colors[level] = c;
            } else {

            }
          }
        }
      }
      this._processName = (ref3 = (ref4 = (ref5 = this.options.processName) != null ? ref5 : (process.argv.length > 1 ? path.basename(process.argv[1], path.extname(process.argv[1])) : void 0)) != null ? ref4 : (process.argv.length > 0 ? path.basename(process.argv[0], path.extname(process.argv[0])) : void 0)) != null ? ref3 : '';
      self = this;
      this._stringifiers = {
        req: exports.stdStringifiers.req,
        err: exports.stdStringifiers.err
      };
      if (this.options.stringifiers != null) {
        ref6 = this.options.stringifiers;
        for (key in ref6) {
          value = ref6[key];
          this._stringifiers[key] = value;
        }
      }
      this._prefixers = (ref7 = this.options.prefixers) != null ? ref7 : {};
      this._out = (ref8 = this.options.out) != null ? ref8 : process.stdout;
      this._basepath = (ref9 = this.options.basepath) != null ? ref9 : process.cwd();
      this._indent = (ref10 = this.options.indent) != null ? ref10 : "  ";
      this._showDate = (ref11 = this.options.showDate) != null ? ref11 : true;
      this._showLoggerName = (ref12 = this.options.showLoggerName) != null ? ref12 : true;
      this._showPid = (ref13 = this.options.showPid) != null ? ref13 : true;
      this._showLevel = (ref14 = this.options.showLevel) != null ? ref14 : true;
      this._showMetadata = (ref15 = this.options.showMetadata) != null ? ref15 : true;
    }

    BunyanDebugStream.prototype._runStringifier = function(entry, key, stringifier, consumed, message) {
      var err, i, len, newMessage, ref1, ref2, result, value;
      consumed[key] = true;
      value = null;
      newMessage = message;
      try {
        if (stringifier == null) {

        } else {
          result = stringifier(entry[key], {
            entry: entry,
            useColor: this._useColor,
            debugStream: this
          });
          if (result == null) {

          } else if (isString(result)) {
            value = result;
          } else {
            ref2 = (ref1 = result.consumed) != null ? ref1 : [];
            for (i = 0, len = ref2.length; i < len; i++) {
              key = ref2[i];
              consumed[key] = true;
            }
            if (result.value != null) {
              if (result.replaceMessage) {
                newMessage = result.value;
                value = null;
              } else {
                value = result.value;
              }
            }
          }
        }
      } catch (_error) {
        err = _error;
        newMessage = message;
        value = "Error running stringifier:\n" + err.stack;
      }
      if (value != null) {
        value = value.replace(/\n/g, "\n" + this._indent);
      }
      return {
        message: newMessage,
        value: value
      };
    };

    BunyanDebugStream.prototype._entryToString = function(entry) {
      var colorsToApply, cols, consumed, date, field, i, key, len, levelPrefix, line, message, prefixer, prefixes, processStr, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, src, start, stringifier, value, valueString, values;
      if (typeof entry === 'string') {
        entry = JSON.parse(entry);
      }
      colorsToApply = this._colors[(ref1 = entry.level) != null ? ref1 : bunyan.INFO];
      src = srcToString(entry.src, this._basepath, this.options.basepathReplacement);
      if (src) {
        src += ': ';
      }
      message = entry.msg;
      consumed = {};
      for (i = 0, len = FIELDS_TO_IGNORE.length; i < len; i++) {
        field = FIELDS_TO_IGNORE[i];
        consumed[field] = true;
      }
      values = [];
      ref2 = this._stringifiers;
      for (key in ref2) {
        stringifier = ref2[key];
        if (entry[key] != null) {
          ref3 = message = this._runStringifier(entry, key, stringifier, consumed, message), message = ref3.message, value = ref3.value;
          if (value != null) {
            values.push("" + this._indent + key + ": " + value);
          }
        } else {
          consumed[key] = true;
        }
      }
      prefixes = [];
      ref4 = this._prefixers;
      for (key in ref4) {
        prefixer = ref4[key];
        if (entry[key] != null) {
          ref5 = this._runStringifier(entry, key, prefixer, consumed, message), message = ref5.message, value = ref5.value;
          if (value != null) {
            prefixes.push(value);
          }
        } else {
          consumed[key] = true;
        }
      }
      if (this._showMetadata) {
        for (key in entry) {
          value = entry[key];
          if (consumed[key]) {
            continue;
          }
          valueString = JSON.stringify(value);
          if (valueString != null) {
            cols = process.stdout.columns;
            start = "" + this._indent + key + ": ";
            if (cols && (valueString.length + start.length) >= cols) {
              valueString = valueString.slice(0, cols - 3 - start.length) + "...";
            }
            values.push("" + start + valueString);
          }
        }
      }
      prefixes = prefixes.length > 0 ? "[" + (prefixes.join(',')) + "] " : '';
      date = this._showDate ? (dateToString((ref6 = entry.time) != null ? ref6 : new Date())) + " " : '';
      processStr = "";
      if (this.options.showProcess) {
        processStr += this._processName;
      }
      if (this._showLoggerName) {
        processStr += entry.name;
      }
      if (this._showPid) {
        processStr += "[" + entry.pid + "]";
      }
      if (processStr.length > 0) {
        processStr += " ";
      }
      levelPrefix = this._showLevel ? ((ref7 = (ref8 = LEVELS[entry.level]) != null ? ref8.prefix : void 0) != null ? ref7 : '      ') + ' ' : '';
      line = "" + date + processStr + levelPrefix + src + prefixes + (applyColors(message, colorsToApply));
      if (typeof request !== "undefined" && request !== null) {
        line += "\n" + this._indent + request;
      }
      if (values.length > 0) {
        line += "\n" + values.map(function(v) {
          return applyColors(v, colorsToApply);
        }).join('\n');
      }
      return line;
    };

    BunyanDebugStream.prototype._write = function(entry, encoding, done) {
      this._out.write(this._entryToString(entry) + "\n");
      return done();
    };

    return BunyanDebugStream;

  })(Writable);

  module.exports = exports = function(options) {
    return new BunyanDebugStream(options);
  };

  serializers = module.exports.serializers = {};

  ref1 = bunyan.stdSerializers;
  for (serializerName in ref1) {
    serializer = ref1[serializerName];
    serializers[serializerName] = serializer;
  }

  serializers.req = function(req) {
    var answer;
    answer = bunyan.stdSerializers.req(req);
    if (answer != null) {
      if (req.user != null) {
        answer.user = req != null ? req.user : void 0;
      }
    }
    return answer;
  };

  serializers.res = function(res) {
    var answer;
    answer = bunyan.stdSerializers.res(res);
    if (answer != null) {
      answer.headers = res._headers;
      if (res.responseTime != null) {
        answer.responseTime = res.responseTime;
      }
    }
    return answer;
  };

  exports.stdStringifiers = {
    req: function(req, arg) {
      var consumed, contentLength, entry, fields, host, ref10, ref11, ref12, ref13, ref14, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, replaceMessage, request, res, responseTime, status, statusCode, statusColor, url, useColor, user;
      entry = arg.entry, useColor = arg.useColor;
      consumed = ['req', 'res'];
      res = entry.res;
      if ((entry['status-code'] != null) && (entry['method'] != null) && (entry['url'] != null) && (entry['res-headers'] != null)) {
        consumed = consumed.concat(EXPRESS_BUNYAN_LOGGER_FIELDS);
      }
      statusCode = (ref2 = res != null ? res.statusCode : void 0) != null ? ref2 : entry['status-code'];
      if (statusCode != null) {
        status = "" + statusCode;
        if (useColor) {
          statusColor = statusCode < 200 ? colors.grey : statusCode < 400 ? colors.green : colors.red;
          status = colors.bold(statusColor(status));
        }
      } else {
        status = "";
      }
      responseTime = (res != null ? res.responseTime : void 0) != null ? res.responseTime : entry.duration != null ? (consumed.push('duration'), entry.duration) : entry["response-time"] != null ? (consumed.push("response-time"), entry["response-time"]) : null;
      if (responseTime != null) {
        responseTime = responseTime + "ms";
      } else {
        responseTime = "";
      }
      user = req.user != null ? ((ref3 = (ref4 = (ref5 = req.user) != null ? ref5.username : void 0) != null ? ref4 : (ref6 = req.user) != null ? ref6.name : void 0) != null ? ref3 : req.user) + "@" : entry.user != null ? (consumed.push("user"), ((ref7 = (ref8 = (ref9 = entry.user) != null ? ref9.username : void 0) != null ? ref8 : (ref10 = entry.user) != null ? ref10.name : void 0) != null ? ref7 : entry.user) + "@") : "";
      contentLength = (ref11 = res != null ? (ref12 = res.headers) != null ? ref12['content-length'] : void 0 : void 0) != null ? ref11 : (ref13 = entry['res-headers']) != null ? ref13['content-length'] : void 0;
      contentLength = contentLength != null ? "- " + contentLength + " bytes" : "";
      host = ((ref14 = req.headers) != null ? ref14.host : void 0) || null;
      url = host != null ? "" + host + req.url : "" + req.url;
      fields = [req.method, user + url, status, responseTime, contentLength];
      fields = fields.filter(function(f) {
        return !!f;
      });
      request = fields.join(' ');
      replaceMessage = !entry.msg || entry.msg === 'request finish';
      return {
        consumed: consumed,
        value: request,
        replaceMessage: replaceMessage
      };
    },
    err: function(err, arg) {
      var debugStream, ref2, ref3, ref4, useColor;
      useColor = arg.useColor, debugStream = arg.debugStream;
      return exceptionFormatter(err, {
        format: useColor ? 'ansi' : 'ascii',
        colors: false,
        maxLines: (ref2 = (ref3 = debugStream.options) != null ? ref3.maxExceptionLines : void 0) != null ? ref2 : null,
        basepath: debugStream._basepath,
        basepathReplacement: (ref4 = debugStream.options) != null ? ref4.basepathReplacement : void 0
      });
    }
  };

}).call(this);
