/////////////////////////////////////////////////////////////////
//	Copyright © 2004-20087 by Symmetrix Software, Inc.
//				Brookfield, Wisconsin
//				ALL RIGHTS RESERVED
  

var LEADING_TRAILING_WS = new RegExp( /(^\s+)|(\s+$)/g );
var LEADING_WS = new RegExp( /^\s+/ );
var TRAILING_WS = new RegExp( /\s+$/ );
var WHITESPACE = " \t\r\n";
/////////////////// Util functions //////////////////////
function formatArgs( text, args )
{
	var result = text.toString();
	
	if ( args )
		{
		// Replace (in result) "%0" with args[0], "%1" with args[1], ....
		for ( var idx = 0; idx < args.length; idx++ )
			{
			var re = new RegExp( "%" + idx.toString(), "g" );
			result = result.replace( re, args[idx] );
			}
		}
		
	return result;
}

// Basically concat all passed arguments with underscores between them.
// Oh, and also lowercase the result.
function makeKey()
{
	var key = "";
	
	for ( var idx = 0; idx < arguments.length; idx++ )
		{
		if ( arguments[idx] )
			key += arguments[idx];
		}
		
	return key.toLowerCase();
}

function ob2Initializer( obj, propName )
{
	var initializer = "";
	if ( propName != null )
		initializer = "'" + propName + "':";
		
	switch ( typeof obj )
		{
		case "boolean":
		case "number":
			initializer += obj.toString();
			break;
		
		case "string":
			initializer += "'";
			initializer += escape( obj );
			initializer += "'";
			break;
		
		case "object":
			if ( obj.constructor == Array )
				{
				initializer += "[";
				for ( var k = 0; k < obj.length; k++ )
					{
					if ( k > 0 )
						initializer += ",";
					initializer += ob2Initializer( obj[k] );
					}
				initializer += "]";
				}
			else
				{
				var firstOne = true;
				initializer += "{";
				for ( pn in obj )
					{
					if ( !firstOne )
						initializer += ",";
						
					initializer += ob2Initializer( obj[pn], pn );
					firstOne = false;
					}
				initializer += "}";
				
				}
			break;
			
		default:
			throw Error( "Unexpected type: " + typeof obj + " for '" + propName + '"' );
		}
		
	return initializer;
}

function getEventPoint( event )
{
	if ( !event )
		return null;
		
	if ( event.pageX != undefined )
		return new Point( event.pageX, event.pageY );
	else if ( event.clientX != undefined )
		return new Point( event.clientX, event.clientY );
	else
		return null;
}

//////////////////// Point Object ////////////////////////////
function Point( x, y )
{
	this.x = x;
	this.y = y;
}

Point.prototype.toString = function()
{
	return formatArgs( "[%0,%1]", [ this.x, this.y ] );
}

//////////////////// Rectangle Object ////////////////////////////
var TOP_LEFT			= 1;
var TOP_RIGHT 		= 2;
var BOTTOM_LEFT		= 3;
var BOTTOM_RIGHT	= 4;

function Rect( x, y, width, height )
{
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
}

Rect.prototype.toString = function()
{
	return formatArgs( "[%0,%1,%2,%3]", [ this.x, this.y, this.width, this.height ] );
}

Rect.prototype.isValid = function()
{
	return !isNaN( this.x ) && !isNaN( this.y ) &&
			  	!isNaN( this.width ) && !isNaN( this.height );
}

Rect.prototype.getCornerPoint = function( whichOne )
{
	if ( !this.isValid() )
		return null;
		
	if ( !whichOne )
		whichOne = TOP_LEFT;
		
	switch ( whichOne )
		{
    case TOP_LEFT:
			return new Point( this.x, this.y );
			
    case TOP_RIGHT:
			return new Point( this.x + this.width, this.y );
			
    case BOTTOM_LEFT:
			return new Point( this.x, this.y + this.height );
			
		case BOTTOM_RIGHT:
			return new Point( this.x + this.width, this.y + this.height );
			
		default:
			return null;
		}
}

Rect.prototype.contains = function( that )
{
	if ( !this.isValid() || !that || !that.isValid() )
		return false;
		
	return this.x <= that.x && this.y <= that.y &&
				 this.width >= that.width && this.height >= that.height;
}

Rect.prototype.overlayOn = function( that, corner )
{
	if ( !this.isValid() || !that || !that.isValid() )
		return false;
		
	if ( !corner )
		corner = TOP_LEFT;
		
	switch ( corner )
		{
    case TOP_LEFT:
			this.x = that.x;
			this.y = that.y;
			break;
			
    case TOP_RIGHT:
			this.x = that.x - ( this.width - that.width );
			this.y = that.y;
			break;
			
    case BOTTOM_LEFT:
			this.x = that.x;
			this.y = that.y - ( this.height - that.height );
			break;
			
		case BOTTOM_RIGHT:
			this.x = that.x - ( this.width - that.width );
			this.y = that.y - ( this.height - that.height );
			break;
			
		default:
			throw new Error( "Unexpected corner type " + corner );
			break;
		}
}

/////////////////// stop watch "class" //////////////////////
function Stopwatch( startIt )
{
	this._elapsedTime = 0;
	if ( startIt )
		this.restart();
};

Stopwatch.prototype.restart = function()
{
	this._start = new Date().getTime();
	this._elapsedTime = 0;
}

Stopwatch.prototype.start = function()
{
	if ( !this._start )
		this._start = new Date().getTime();
}

Stopwatch.prototype.stop = function()
{
	if ( this._start )
		{
		this._elapsedTime += new Date().getTime() - this._start;
		this._start = null;
		}
}

Stopwatch.prototype.getET = function()
{
	if ( this._start )
		return this._elapsedTime + new Date().getTime() - this._start;
	else
		return this._elapsedTime;
}

/////////////////// My Little Tracer (MLT) //////////////////////
function MLT(){};
MLT.console = null;
MLT.lineCount = 0;
MLT.enabled = true;

MLT.enable = function( enableIt )
{
	MLT.enabled = enableIt == null || enableIt ? true : false;
}

MLT.trace = function( msg )
{
	if ( !MLT.enabled )
		return;
		
	if ( !MLT.console || MLT.console.closed )
		{
		MLT.console = window.open( "", "MLTConsole", "width=800,height=300,resizable,scrollbars" );
		if ( !MLT.console )
			return;
		
		MLT.console.document.open( "text/html" );
		MLT.console.document.write( "<html><head><title>ProdlogiX JavaScript Trace Console</title></head><body><hr>" );
		MLT.console.document.writeln( "<pre style='margin-top: 0; margin-bottom: 0'>" );
		}
	
	MLT.console.document.write( "[" + MLT.lineCount++ + "] " );	
	MLT.console.document.writeln( formatArgs( msg, arguments ) );
	MLT.console.focus();
} 

MLT.traceImages = function()
{
	for ( var idx = 0; idx < document.images.length; idx++ )
		this.trace( "[%1] src=%2, width=%3, height=%4",
								idx,  
								document.images[idx].src,
								document.images[idx].width,
								document.images[idx].height );	
}

// Use sparingly....
// MLT.traceObjectProps( window ) and MLT.traceObjectProps( document ) will fail
// because it seems that many of the properties are not full JavaScript objects. 
MLT.traceObjectProps = function( obj )
{
	this.trace( obj )
	for ( var propName in obj )
		this.trace( ">>>%1[%2]=%3", obj, propName, obj[ propName ] );
}


