// print stack trace: from http://eriwen.com/javascript/js-stack-trace/
function getStackTrace() {
	try {
	    var callstack = [];
	    var haveStack = false;
	    try {
	    	i.dont.exist+=0; /* doesn't exist- that's the point */
	    } catch(e) {
	        if (e.stack) { // Firefox
	            var lines = e.stack.split('\n');
	            for (var i=0, len=lines.length; i<len; i++) {
	                if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
	                    callstack.push(lines[i]);
	                }
	            }
	            callstack.shift(); // Remove call to getStackTrace()
	            haveStack = true;
	        } else if (window.opera && e.message) { // Opera
	            var lines = e.message.split('\n');
	            for (var i=0, len=lines.length; i<len; i++) {
	                if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
	                    var entry = lines[i];
	                    // Append next line also since it has the file info
	                    if (lines[i+1]) {
	                        entry += " at " + lines[i+1];
	                        i++;
	                    }
	                    callstack.push(entry);
	                }
	            }
	            callstack.shift(); // Remove call to getStackTrace()
	            haveStack = true;
	        }
	    }
	    if (!haveStack) { // IE and webkit...
	        var cur = arguments.callee.caller;
	        while (cur) {
	            var fn = cur.toString();
	            var end = fn.indexOf('{');
	            if (end <= 0) end = fn.length;
	            callstack.push(fn.substring(fn.indexOf("function"), end) || 'anonymous');
	            cur = cur.caller;
	        }
	    }
	    return callstack.join('\n');
	} catch (exc) {
		return 'Error computing stack: ' + (exc.message || exc.description);
	}
};

// error reporting
function __report_error(msg, url, line, extraData) {
    try {
        var path = document.location.href;
        path = path.replace(new RegExp('^([^:]+://[^/]+/(~[^/]+/)?).*'), '$1');
        var params = {
        	'ua':      navigator.userAgent,
            'source':  document.location.href,
            'message': msg,
            'url':     url,
            'line':    line,
            'extra':   extraData || getStackTrace()
        };
        new Ajax.Request(path + 'ws/jsError', { 'parameters': params, 'method': 'post' });
        window.onbeforeunload = null; // prevent further unload prompts
        alert('An unrecoverable error has been detected in the editor. Support has been automatically notified. Please reload the page to try again. If problem persists, please email help@tikatok.com for further assistance.');
    } catch (e) {
        alert('Error while reporting crash. Please email help@tikatok.com for support.\nMessage: ' + (e.message || e.description));
    }
};

function __report_exception(e, msg) {
	__report_error(
	    (msg ? (msg + ': ') : '') + (e.name || (e.number ? ('Code ' + e.number) : 'unknown error')) + ': ' + (e.message || e.description),
	        e.fileName || '?', e.lineNumber || '?', e.stack || null);
};

Function.prototype.bind = function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function() {
        try {
            return __method.apply(object, args.concat($A(arguments)));
        } catch (e) {
            __report_exception(e);
            throw e;
        }
    }
};

Function.prototype.bindAsEventListener = function(object) {
    var __method = this, args = $A(arguments), object = args.shift();
    return function(event) {
        try {
            return __method.apply(object, [event || window.event].concat(args));
        } catch (e) {
            __report_exception(e);
            throw e;
        }
    }
};

window.onerror = __report_error;

Ajax.Responders.register({
    'onException': function(request, e) {
        __report_exception(e, 'Error in RPC to ' + request.url);
    }
});

