﻿Type.registerNamespace('Ajax.Logging');

Ajax.Logging.BaseListener = function(lineSeparator)
{
    this._lineSeparator = '\n';

    if (lineSeparator)
    {
        this._lineSeparator = lineSeparator;
    }
}

Ajax.Logging.BaseListener.prototype =
{
    get_lineSeparator : function()
    {
        if (arguments.length !== 0) throw Error.parameterCount();

        return this._lineSeparator;
    },

    dispose : function()
    {
    },

    publishException : function(errorCode, exception, environmentInfo)
    {
        throw Error.notImplemented();
    },

    formatException : function(errorCode, exception)
    {
        var lineSeparator = this.get_lineSeparator();
        var errorInfo = new Sys.StringBuilder();

        errorInfo.append('Error Code: ' + errorCode.toString() + lineSeparator);

        if (typeof exception.get_exceptionType != 'undefined')
        {
            errorInfo.append(   'Message: ' + exception.get_message() + lineSeparator +
                                'Type: ' + exception.get_exceptionType() + lineSeparator +
                                'StackTrace: ' + exception.get_stackTrace()
                            );
        }
        else
        {
            errorInfo.append(   'Message: ' + exception.message + lineSeparator +
                                'Type: ' + exception.name + lineSeparator +
                                'Description: ' + exception.description
                            );

            //Only Update Panel has this field
            if (typeof exception.httpStatusCode != 'undefined')
            {
                errorInfo.append(lineSeparator + 'HttpStatusCode: ' + exception.httpStatusCode);
            }

            //Only Unhandled error have the following two fields
            if (typeof exception.lineNumber != 'undefined')
            {
                errorInfo.append(lineSeparator + 'LineNumber: ' + exception.lineNumber);
            }

            if (typeof exception.url != 'undefined')
            {
                errorInfo.append(lineSeparator + 'Url: ' + exception.url);
            }
        }

        return errorInfo.toString();
    }
}

Ajax.Logging.BaseListener.registerClass('Ajax.Logging.BaseListener', null, Sys.IDisposable);


Ajax.Logging.ExceptionManager = function()
{
    this._listeners = new Array();
    Ajax.Logging.ExceptionManager.initializeBase(this);
}

Ajax.Logging.ExceptionManager.prototype =
{
    initialize : function()
    {
        Ajax.Logging.ExceptionManager.callBaseMethod(this, 'initialize');
    },

    dispose : function()
    {
        this.clearListeners();

        delete this._listeners;

        Ajax.Logging.ExceptionManager.callBaseMethod(this, 'dispose');
    },

    addListener : function(listener)
    {
        var e = Function._validateParams(arguments, [{name: 'listener', type: Ajax.Logging.BaseListener}]);
        if (e) throw e;

        Array.add(this._listeners, listener);
    },

    removeListener : function(listener)
    {
        var e = Function._validateParams(arguments, [{name: 'listener', type: Ajax.Logging.BaseListener}]);
        if (e) throw e;

        listener.dispose();

        Array.remove(this._listeners, listener);
    },

    clearListeners : function()
    {
        if (this._listeners.length > 0)
        {
            for(var i = 0; i < this._listeners.length; i++)
            {
                this._listeners[i].dispose();
            }

            Array.clear(this._listeners);
        }
    },

    publishException : function(errorCode, exception)
    {
        var e1 = Function._validateParams(arguments, [{name: 'errorCode', type: Number}, {name: 'exception', type: Error}]);
        var e2 = Function._validateParams(arguments, [{name: 'errorCode', type: Number}, {name: 'exception', type: Sys.Net.WebServiceError}]);

        if ((e1) && (e2))
        {
            throw e1;
        }

        if (this._listeners.length > 0)
        {
            var environmentInfo = this._getEnvironmentInfo();

            for(var i = 0; i < this._listeners.length; i++)
            {
                this._listeners[i].publishException(errorCode, exception, environmentInfo);
            }
        }
    },

    _getEnvironmentInfo : function()
    {
        var scriptTags = document.getElementsByTagName('script');
        var scripts = new Array(); 

        if (scriptTags)
        {
            for(var i = 0; i < scriptTags.length; i++)
            {
                var scriptTag = scriptTags[i];

                if (typeof scriptTag.src != 'undefined')
                {
                    if (scriptTag.src.length > 0)
                    {
                        Array.add(scripts, scriptTag.src + ' : ' + scriptTag.readyState);
                    }
                }
            }
        }

        var url = window.location.href;

        var referrer = '';

        if (document.referrer)
        {
            if (document.referrer.length > 0)
            {
                referrer = document.referrer;
            }
        }

        return {url:url, referrer:referrer, scripts:scripts};
    }
}

Ajax.Logging.ExceptionManager.registerClass('Ajax.Logging.ExceptionManager', Sys.Component);

//Making the ExceptionManager a Singleton Class, but unfortunately
//there is no way to restrict its constructor to be called.

Ajax.Logging.ExceptionManager._staticInstance = $create(Ajax.Logging.ExceptionManager, {'id':'exceptionManager'});

Ajax.Logging.ExceptionManager.getInstance = function()
{
    return Ajax.Logging.ExceptionManager._staticInstance;
}

if (typeof(Sys) != 'undefined')
{
    Sys.Application.notifyScriptLoaded();
}