/*
*   File Name:      SS.debug.js
*   Description:    Javascript debugging
*   Author:         Allen Evans
*/

/*
*   Dependencies
*   ----------------------------------------
*   SS.global.js
*   SS.core.js
*   SS.locale.js
*/

/**
*   @class          SS.debug
*   @static
*   @description    JavaScript debugging class. Allows debug output to a console window.
*/
SS.debug = {
                                /**
                                *   @property {HTMLElement} console
                                *   @description            Name of the element where the output is written to.
                                */
				console		:	$g("$$debug_console"),
				                /**
				                *   @function           toconsole
				                *   @description        Inspect the object and output to console.
				                *   @param {Object}  o  Object to be inspected
				                *   @param {Boolean} f  (Optional) Include functions of object. Default = false.
				                *   @returns            null
				                */
				toconsole	:	function(o,f)
								{
									var c = SS.debug.console, canvas;
									if(!c)
									{
									    c = window.open("","SS_DEBUG","status=0,toolbar=0,width=640,height=480");
									    SS.debug.console = c;
									    
									    if(c)
									    {
									        var d = c.document, b = d.body, bar = d.createElement("DIV"), close = d.createElement("DIV");
									        canvas = d.createElement("DIV");
									        d.title = "Javascript Debug Window - SpiderScript - By Allen Evans";
    									    
    									    b.style.overflow = "hidden";
    									    
    									    $dc(b);
    									    b.style.margin = 0;
    									    b.style.padding = 0;
    									    b.style.fontFamily = "Arial";
    									    b.style.fontSize = "smaller";
    									    
    									    canvas.id = "$$debug_console";
    									    $w(canvas,"100%");
    									    canvas.style.styleFloat = "left";
    									    canvas.style.cssFloat = "left";
    									    canvas.style.overflow = "auto";
    									    
    									    canvas.style.backgroundColor = "#BBBBBB";
    									    
    									    var onresize =      function()
    									                        {
    									                            var canvas = c.document.getElementById("$$debug_console");
    									                           
    									                            if(c.innerHeight)
                                                                    {
                                                                        $h(canvas,c.innerHeight-22);
                                                                    }
                                                                    else if(c.document.body.clientHeight)
                                                                    {
                                                                        $h(canvas,c.document.body.clientHeight-22);
                                                                    }
        									                        
    									                        };
    									    c.onresize = onresize;
    									    b.onresize = onresize;
    									    
    									    $w(bar,"100%");
    									    $h(bar,21);
    									    bar.style.backgroundColor = "#333333";
    									    bar.style.styleFloat = "left";
    									    bar.style.cssFloat = "left";
    									    
    									    close.innerHTML = "x";
    									    close.style.styleFloat = "right";
    									    close.style.cssFloat = "right";
    									    close.style.border = "solid 1px #BBBBBB";
    									    close.style.backgroundColor = "#333333";
    									    close.style.color = "#BBBBBB";
    									    close.style.margin = "2 2 0 0";
    									    close.style.fontSize = "12px";
    									    close.style.cursor = "pointer";
    									    close.style.textAlign = "center";
    									    close.style.fontFamily = "Arial";
    									    $h(close,"16");
    									    $w(close,16);
    									    
                                            /**
                                            *   @ignore
                                            */
    									    close.onclick = function()
    									                    {
    									                        c.close();
    									                    };
    									    
    									    bar.appendChild(close);
    									    b.appendChild(bar);
    									    b.appendChild(canvas);
    									    
                                            if(c.innerWidth)
                                            {
                                                $h(canvas,c.innerHeight-22);
                                            }
                                            else if(b.clientWidth)
                                            {
                                                $h(canvas,b.clientHeight-22);
                                            }
    									        									    
									    }
									    else
									    {
									        //failed to create window. are popup blockers enabled?
									    }
									}
									
									if(c)
									{
										try
										{
									        canvas = c.document.getElementById("$$debug_console");
										    var l = c.document.createElement("DIV"), txt = c.document.createTextNode(o), k;
    										
    									    l.style.styleFloat = "left";
    									    l.style.cssFloat = "left";
    									    $w(l,"100%");
    									    l.style.height = "auto";
    									    
										    canvas.appendChild(l);
    										
										    l.appendChild(txt);
										    
										    if(typeof o != "string")
										    {
											    for(k in o)
											    {
											        try
											        {
												        if(!f && $isf(o[k]))
												        {
													        //ignore
												        }
												        else
												        {
													        var nl = c.document.createElement("DIV"), t = c.document.createTextNode(k + "= " + o[k] + "\n");
													        nl.style.styleFloat = "left";
    									                    nl.style.cssFloat = "left";
    									                    $w(nl,"100%");
        													
													        nl.appendChild(t);
													        l.appendChild(nl);
												        }
												    }
												    catch(y)
												    {
												    }
											    }
											}
											
										    try
										    {
										        var nlb = c.document.createElement("DIV"), tb = c.document.createTextNode(" ");
										        nlb.appendChild(tb);
										        l.appendChild(nlb);
										    }
										    catch(x)
										    {}
										}
										catch(ex)
										{
										}
										
										
										
									}
					}
			};

/**
*   @class          SS.stopwatch
*   @static
*   @description    Stopwatch for timing the durations of events. i.e how long does a peice of code take to execute.
*/
SS.stopwatch =	{
                                    /**
                                    *   @property {Object}  watches
                                    *   @description        Object to hold StopwatchEvent instances referenced by an
                                    *                       arbitrary name.
                                    */
						watches	:	{},
						            /**
						            *   @class  StopwatchEvent holds timing information.
						            *   @constructor
						            */
						StopwatchEvent	:	function()
									        {
										        this.sd = new Date();
										        this.dur = 0;
										        this.ed = null;
									        },
									/**
									*   @function               SS.stopwatch.start
									*   @description            Instantiates a new StopwatchEvent stored agaisnt the assigned name.
									*   @param {String} name    Name of the stopwatch.
									*   @returns                null
									*/
						start	:	function(name)
									{
										SS.stopwatch.watches[name] = new SS.stopwatch.StopwatchEvent();
									},
									/**
									*   @function               SS.stopwatch.resume
									*   @description            Resumes a current stopwatch from a stopped state or creates a new instance
									*                           of the stopwatch referenced by the specified name
									*   @param {String} name    Name of the stopwatch.
									*   @returns                null
									*/
						resume	:	function(name)
									{
										if(SS.stopwatch.watches[name])
										{
											SS.stopwatch.watches[name].sd = new Date();
											SS.stopwatch.watches[name].ed = null;
										}
										else
										{
											this.start(name);
										}
									},
									/**
									*   @function               SS.stopwatch.stop
									*   @description            Stops an active stopwatch.
									*   @param {String} name    Name of the stopwatch.
									*   @returns                null
									*/
						stop	:	function(name)
									{
										if(SS.stopwatch.watches[name])
										{
											SS.stopwatch.watches[name].stop();
										}
									},
									/**
									*   @function               SS.stopwatch.duration
									*   @description            Returns the number of seconds that the stopwatch was active for.
									*                           I.e. Difference between the start and finish times.
									*   @param {String} name    Name of the stopwatch.
									*   @returns {Number}       Duration in seconds.
									*/
						duration:	function(name)
									{
										var r = -1;
										
										if(SS.stopwatch.watches[name])
										{
											r = Number(SS.stopwatch.watches[name].dur/1000);
										}
										
										return r;
									},
									/**
									*   @function               SS.stopwatch.average
									*   @description            Returns the average number of seconds that the matching stopwatches were active for.
									*                           I.e. Difference between the start and finish times.
									*   @param {String} name    (Optional) Name of the stopwatch. If specified, then any stopwatch which contains part of
									*                           the name will be used to calculate the average. If null then all stopwatches will be used
									*                           to calculate the average.
									*   @returns {Number}       Duration in seconds.
									*/
				        average:    function(name)
				                    {
				                        var sum = 0, count = 0, tn;
				                        
				                        for(tn in SS.stopwatch.watches)
				                        {
				                            if($ise(name))
				                            {
				                                sum += Number(SS.stopwatch.watches[tn].dur/1000);
				                                count++;
				                            }
				                            else if(tn.match(new RegExp(name)))
				                            {
				                                sum += Number(SS.stopwatch.watches[tn].dur/1000);
				                                count++;
				                            }
				                        
				                        }
				                        
				                        return (count) ? (sum / count) : 0;
				                    }
									
					};

SS.stopwatch.StopwatchEvent.prototype	=	{
                                                /**
                                                *   @function       stop
                                                *   @description    Stops an active {@link StopwatchEvent}.
                                                */
									stop	:	function()
												{
													//Set the end date to be now
													this.ed = new Date();
													this.dur = this.dur + Number(this.ed - this.sd);
												}
								            };

/**
*   @function           $debug
*   @description        Inspect the object and output to console.
*                       Pseudonym for {@link SS.debug.console}
*   @param {Object}  o  Object to be inspected
*   @param {Boolean} f  (Optional) Include functions of object. Default = false.
*   @returns            null
*/
function $debug(d,f)
{
	SS.debug.toconsole(d,f);
}
/**
*   @function           $stopwatch
*   @description        Pseudonym for {@link SS.debug.console}.
*/
var $stopwatch = SS.stopwatch;