var NotifyError = (function(){
  var notify_error  = function(message_or_error) {
    var error_message = message_or_error.message  || message_or_error.toString();
    var error_class   = message_or_error.name     || 'Notification';
    output("Reporting error " + error_class + ": " + error_message);

    jQuery.post(t_url('/errors'),
      { 'error_message' : error_message,
        'error_class'   : error_class,
        'url'           : window.location.href,
        'backtrace[]'   : get_stack_trace()
      }
    );
  }

  var output = function(message) {
    window.console && window.console.debug && console.debug(message);
  }

  var get_stack_trace = function() {
    try {
      // Inspired by http://eriwen.com/javascript/js-stack-trace/
      var callstack = [];
      var browser = jQuery.browser;
      var is_chrome = /chrome/.test( navigator.userAgent.toLowerCase() );
      if (browser.msie || browser.safari && !is_chrome) {
        // The following stack trace sucks, but apparently it's the best we can get
        // from Safari and IE
        var currentFunction = arguments.callee.caller;
        while (currentFunction) {
          var fn = currentFunction.toString();
          var fname = fn.split("\n")[0].match(/([^{]+)/)[0];
          callstack.push(fname);
          currentFunction = currentFunction.caller;
        }
      } else {
        try {
          i.dont.exist+=0; //doesn't exist- that's the point
        } catch(e) {
          if (jQuery.browser.mozilla) { 
            var stack = e.stack.split("\n");
            jQuery.each(stack, function(){
              callstack.push(this.toString().replace(/(.*)@(.*)\?\d+:(\d*)/, function(str, m1, m2, m3, offset, s){
                var func = m1.match(/^\(.*\)$/) ?
                            m1.replace(/^\((.*)\)$/, "$1") : // remove parens around ([object Object])
                            m1;
                return m2 + ":" + m3 + " (in " + func + ")";
              }));
            });
          } else if (is_chrome) {
            var stack = e.stack.split("\n");
            jQuery.each(stack, function() {
              callstack.push(this.toString().replace(/.*(http.+)\?\d+:(\d+):.*/, "$1:$2"));
            });
          } else if (jQuery.browser.opera) {
            var lines = e.message.split("\n");
            for (var i=0, len=lines.length; i<len; i++) {
              var line = lines[i];
              if (line.match(/^\s+Line/)) {
                var file  = line.replace(/\s*Line\s(\d+).*(http.*)\?\d*.*\r?/, "$2:$1");
                var fname = "anonymous";
                if (line.match(/in\sfunction\s(.*)\r?/i))
                  fname = line.match(/in\sfunction\s(.*)\r?/i)[1];
                callstack.push(file + " (in " + fname + ")");
              }
            }
          }
          //Remove calls to get_stack_trace
          callstack.shift();
        }
      }
      //Remove call to notify_error
      callstack.shift();
      return callstack;
    } catch (e) {
      return ['Error trying to get a stack trace.'];
    }
  }

  return {
    notify_error: notify_error,
    output:       output
  }
})();

var notify_error  = NotifyError.notify_error;
var output        = NotifyError.output;
