////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////

var __CFERROR_DEBUG_PRE_LOADED_ERRORS = true;
var __CFERROR_INSTALL_ALERT_HANDLER = true;
var __CFERROR_INSTALL_ONERROR_HANDLER = true;
var __CFERROR_SHOW_STACK = true;

// XXX: This doesn't take care of JavaScript 1.4 browsers.
var __CFERROR_SUPPORTS_EXCEPTIONS = !! window.Error;

var __CFERROR_WARNING_EXCEPTIONS = "browser appears to lack exception support";

////////////////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////////////////

var __cfErrorHandlerSet = new CFEventHandlerSet();

////////////////////////////////////////////////////////////////////////////////
// Private functions
////////////////////////////////////////////////////////////////////////////////

function __cfErrorDisplayAlertBox(message, url, lineNumber, stack, loadStatus)
{
    var msg = "A JavaScript error has occurred.  Here are the details:\n\n";
    if (message) {
        msg += "\tMessage: " + message + '\n';
    }
    if (url) {
        msg += "\tURL: " + url + '\n';
    }
    if (lineNumber) {
        msg += "\tLine Number: " + lineNumber + '\n';
    }
    if (loadStatus) {
        msg += "\tLoad Status: " + loadStatus + '\n';
    }
    if (stack && __CFERROR_SHOW_STACK) {
        msg += "\nStack:\n\n" + stack + '\n';
    }
    msg += "\nWe apologize for the inconvenience.";
    window.alert(msg);
    return true;
}

function __cfErrorHandle(message, url, lineNumber, stackTrace)
{
    var loadStatus = cfDocumentGetLoadStatusMessage();
    if (__CFERROR_DEBUG_PRE_LOADED_ERRORS) {
        __cfErrorDisplayAlertBox(message, url, lineNumber, stackTrace,
                                 loadStatus);
    } else {
        var args = new Array();
        args.push(__cfErrorHandleLoaded);
        args.push(message);
        args.push(url);
        args.push(lineNumber);
        args.push(stackTrace);
        args.push(loadStatus);
        cfDocumentAddOnLoadedCallback.apply(undefined, args);
    }
}

function __cfErrorHandleDocumentLoadedEvent()
{
    __cfErrorHandle = __cfErrorHandleLoaded;
}

function __cfErrorHandleException(e)
{
    __cfErrorHandle(e.message || e.toString(), e.fileName, e.lineNumber,
                    e.stack);
}

function __cfErrorHandleLoaded(message, url, lineNumber, stackTrace, loadStatus)
{
    if (typeof(loadStatus) == "undefined") {
        loadStatus = cfDocumentGetLoadStatusMessage();
    }
    __cfErrorHandlerSet.execute(message, url, lineNumber, stackTrace,
                                loadStatus);
}

function __cfErrorHandleWindowError(message, url, lineNumber)
{
    __cfErrorHandle(message, url, lineNumber, undefined);
    return true;
}

function __cfErrorTriggerNoException(message)
{
    __cfErrorHandle(message, undefined, undefined, undefined);
    return undefined;
}

function __cfErrorWatch(obj, func, args)
{
    if (typeof(args) == "undefined") {
        args = new Array();
    }
    return func.apply(obj, args);
}

////////////////////////////////////////////////////////////////////////////////
// Public API
////////////////////////////////////////////////////////////////////////////////

function cfErrorAddOnErrorCallback()
{
    __cfErrorHandlerSet.add.apply(__cfErrorHandlerSet, arguments);
}

function cfErrorHasExceptionSupport()
{
    return __CFERROR_SUPPORTS_EXCEPTIONS;
}

////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////

if (__CFERROR_SUPPORTS_EXCEPTIONS) {
    cfErrorTrigger = new Function("s", "throw new Error(s);");
    cfErrorWatch = new Function("obj, func, args, ignoreError, errorResult",
                                "try { " +
                                "    return __cfErrorWatch(obj, func, args);" +
                                "} catch (e) {" +
                                "    if (! ignoreError) {" +
                                "        __cfErrorHandleException(e);" +
                                "    }" +
                                "}" +
                                "return errorResult;");
} else {
    cfErrorTrigger = __cfErrorTriggerNoException;
    cfErrorWatch = __cfErrorWatch;
    cfWarningTrigger(__CFERROR_WARNING_EXCEPTIONS);
}
if (__CFERROR_INSTALL_ALERT_HANDLER) {
    cfErrorAddOnErrorCallback(__cfErrorDisplayAlertBox);
}
if (__CFERROR_INSTALL_ONERROR_HANDLER) {
    window.onerror = __cfErrorHandleWindowError;
}
cfDocumentAddOnLoadedCallback(__cfErrorHandleDocumentLoadedEvent);

