// Generated by CoffeeScript 1.8.0
var ParsedError, prop, sysPath, _fn, _i, _len, _ref;

sysPath = require('path');

module.exports = ParsedError = (function() {
  function ParsedError(error) {
    this.error = error;
    this._parse();
  }

  ParsedError.prototype._parse = function() {
    var m;
    this._trace = [];
    this._kind = 'Error';
    this._wrapper = '';
    if (this.error.wrapper != null) {
      this._wrapper = String(this.error.wrapper);
    }
    if (typeof this.error !== 'object') {
      this._message = String(this.error);
    } else {
      this._stack = this.error.stack;
      if (this.error.kind != null) {
        this._kind = String(this.error.kind);
      } else if (typeof this._stack === 'string') {
        if (m = this._stack.match(/^([a-zA-Z0-9\_\$]+):\ /)) {
          this._kind = m[1];
        }
      }
      if (typeof this._stack === 'string') {
        this._parseStack();
      } else {
        this._message = (this.error.message != null) && String(this.error.message) || '';
      }
    }
  };

  ParsedError.prototype._parseStack = function() {
    var line, message, messageLines, reachedTrace, _i, _len, _ref;
    messageLines = [];
    reachedTrace = false;
    _ref = this._stack.split('\n');
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      line = _ref[_i];
      if (line.trim() === '') {
        continue;
      }
      if (reachedTrace) {
        this._trace.push(this._parseTraceItem(line));
      } else {
        if (line.match(/^\s*at\s.+/)) {
          reachedTrace = true;
          this._trace.push(this._parseTraceItem(line));
        } else {
          messageLines.push(line);
        }
      }
    }
    message = messageLines.join('\n');
    if (message.substr(0, this._kind.length) === this._kind) {
      message = message.substr(this._kind.length, message.length).replace(/^\:\s+/, '');
    }
    this._message = message;
  };

  ParsedError.prototype._parseTraceItem = function(text) {
    var addr, col, d, dir, file, jsCol, jsLine, line, m, original, packageName, packages, path, r, remaining, shortenedAddr, shortenedPath, what;
    text = text.trim();
    if (text === '') {
      return;
    }
    if (!text.match(/^at\ /)) {
      return text;
    }
    text = text.replace(/^at /, '');
    if (text === 'Error (<anonymous>)' || text === 'Error (<anonymous>:null:null)') {
      return;
    }
    original = text;
    what = null;
    addr = null;
    path = null;
    dir = null;
    file = null;
    line = null;
    col = null;
    jsLine = null;
    jsCol = null;
    shortenedPath = null;
    shortenedAddr = null;
    packageName = '[current]';
    if (m = text.match(/\(([^\)]+)\)$/)) {
      addr = m[1].trim();
    }
    if (addr != null) {
      what = text.substr(0, text.length - addr.length - 2);
      what = what.trim();
    }
    if (addr == null) {
      addr = text.trim();
    }
    addr = this._fixPath(addr);
    remaining = addr;
    if (m = remaining.match(/\,\ <js>:(\d+):(\d+)$/)) {
      jsLine = m[1];
      jsCol = m[2];
      remaining = remaining.substr(0, remaining.length - m[0].length);
    }
    if (m = remaining.match(/:(\d+):(\d+)$/)) {
      line = m[1];
      col = m[2];
      remaining = remaining.substr(0, remaining.length - m[0].length);
      path = remaining;
    }
    if (path != null) {
      file = sysPath.basename(path);
      dir = sysPath.dirname(path);
      if (dir === '.') {
        dir = '';
      }
      path = this._fixPath(path);
      file = this._fixPath(file);
      dir = this._fixPath(dir);
    }
    if (dir != null) {
      d = dir.replace(/[\\]{1,2}/g, '/');
      if (m = d.match(/node_modules\/([^\/]+)(?!.*node_modules.*)/)) {
        packageName = m[1];
      }
    }
    if (jsLine == null) {
      jsLine = line;
      jsCol = col;
    }
    if (path != null) {
      r = this._rectifyPath(path);
      shortenedPath = r.path;
      shortenedAddr = shortenedPath + addr.substr(path.length, addr.length);
      packages = r.packages;
    }
    return {
      original: original,
      what: what,
      addr: addr,
      path: path,
      dir: dir,
      file: file,
      line: parseInt(line),
      col: parseInt(col),
      jsLine: parseInt(jsLine),
      jsCol: parseInt(jsCol),
      packageName: packageName,
      shortenedPath: shortenedPath,
      shortenedAddr: shortenedAddr,
      packages: packages || []
    };
  };

  ParsedError.prototype._getMessage = function() {
    return this._message;
  };

  ParsedError.prototype._getKind = function() {
    return this._kind;
  };

  ParsedError.prototype._getWrapper = function() {
    return this._wrapper;
  };

  ParsedError.prototype._getStack = function() {
    return this._stack;
  };

  ParsedError.prototype._getArguments = function() {
    return this.error["arguments"];
  };

  ParsedError.prototype._getType = function() {
    return this.error.type;
  };

  ParsedError.prototype._getTrace = function() {
    return this._trace;
  };

  ParsedError.prototype._fixPath = function(path) {
    return path.replace(/[\\]{1,2}/g, '/');
  };

  ParsedError.prototype._rectifyPath = function(path, nameForCurrentPackage) {
    var m, packages, parts, remaining, rest;
    path = String(path);
    remaining = path;
    if (!(m = path.match(/^(.+?)\/node_modules\/(.+)$/))) {
      return {
        path: path,
        packages: []
      };
    }
    parts = [];
    packages = [];
    if (typeof nameForCurrentPackage === 'string') {
      parts.push("[" + nameForCurrentPackage + "]");
      packages.push("[" + nameForCurrentPackage + "]");
    } else {
      parts.push("[" + (m[1].match(/([^\/]+)$/)[1]) + "]");
      packages.push(m[1].match(/([^\/]+)$/)[1]);
    }
    rest = m[2];
    while (m = rest.match(/([^\/]+)\/node_modules\/(.+)$/)) {
      parts.push("[" + m[1] + "]");
      packages.push(m[1]);
      rest = m[2];
    }
    if (m = rest.match(/([^\/]+)\/(.+)$/)) {
      parts.push("[" + m[1] + "]");
      packages.push(m[1]);
      rest = m[2];
    }
    parts.push(rest);
    return {
      path: parts.join("/"),
      packages: packages
    };
  };

  return ParsedError;

})();

_ref = ['message', 'kind', 'arguments', 'type', 'stack', 'trace', 'wrapper'];
_fn = function() {
  var methodName;
  methodName = '_get' + prop[0].toUpperCase() + prop.substr(1, prop.length);
  return Object.defineProperty(ParsedError.prototype, prop, {
    get: function() {
      return this[methodName]();
    }
  });
};
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  prop = _ref[_i];
  _fn();
}
