var _loadTimeStart = new Date();
var _loadBindEvent = "load";

/*	Define IPC namespaces	*/
		var IPC = {};
		var $NS = function()  {
			$A( arguments ).each( function( ns ) {
				var r = IPC;
				ns = ns.split( '.' );
				if ( ns[0] == 'IPC' ) ns.shift();
				ns.each( function( n ) {
					if ( !( r[n] instanceof Object ) ) r[n] = {};
					r = r[n];
				} );
			} );
		};
		
		$NS( 'CONFIG', 'DOM', 'HANDLE' );
		
		IPC.CONFIG._namespace = '___ipc_sys___';
		IPC.DOM._emptyNode = document.createElement( 'span' );
		IPC.HANDLE._emptyFunction = Prototype.emptyFunction;
		
		var NODE = {
			ELEMENT : 1,
			ATTRIBUTE : 2,
			TEXT : 3,
			CDATA_SECTION : 4,
			ENTITY_REFERENCE : 5,
			ENTITY : 6,
			PROCESSING_INSTRUCTIONS : 7,
			COMMENT : 8,
			DOCUMENT : 9,
			DOCUMENT_TYPE : 10,
			DOCUMENT_FRAGMENT : 11,
			NOTATION : 12
		};
		
		var TEST = {
			array : function( v ) { return this.object( v ) && v.constructor === Array; }, 
			'boolean' : function( v ) { return typeof v === 'boolean'; }, 
			cssImportRule : function( v ) { return ( TEST.object( v ) && /^@import.*$/i.test( v.cssText ) ) ? true : false; }, 
			cssMediaRule : function( v ) { return ( TEST.object( v ) && /^@media.*$/im.test( v.cssText ) ) ? true : false; }, 
			cssStyleSheet : function( v ) { return ( TEST.object( v ) && ( v.rules || v.cssRules || v.sheet.cssRules ) ) ? true : false; }, 
			empty : function( v ) { return v === ''; }, 
			func : function( v ) { return typeof v === 'function'; }, 
			htmlElement : function( v ) { return v.nodeType === NODE.ELEMENT; }, 
			node : function( v ) {
				return $H( NODE ).find( function( n ) {
					return v.nodeType == n.value ? n.key.toLowerCase().replace( /_/g, " " ) : false;
				} );
			}, 
			number : function( v ) { return typeof v === 'number'; }, 
			object : function( v ) { return ( v && typeof v === 'object' ) || this.func( v ); }, 
			regex : function( v ) { return v && v.constructor === RegExp; }, 
			string : function( v ) { return typeof v === 'string'; }, 
/*			typeof : function( v ) {
				if ( this.htmlElement( v ) ) return 'HTMLElement';
				else if ( this.array( v ) ) return 'array';
				else if ( this.func( v ) ) return 'function';
				else if ( this.regex( v ) ) return 'regexp';
				else if ( this.null( v ) ) return null;
				else if ( this.object( v ) ) return 'object';
				else if ( this.undefined( v ) ) return 'undefined';
				else if ( this.number( v ) ) return 'number';
				else if ( this.string( v ) ) return 'string';
				else if ( this.boolean( v ) ) return 'boolean';
				else throw 'Error: Unkown type';
			}, */
			'null' : function( v ) { return typeof v === 'object' && !v; }, 
			undefined : function( v ) { return typeof v === 'undefined'; }
		};

/*	Dom loops through a series of JS Objects and/ or Strings with HTML in them and creates their DOM equivellants and returns them	*/
		IPC.CreateDOM = function( obj ) {
			if ( TEST.string( obj ) )
				return $B.eval( obj );
				
			var dom = {};
			for ( $_ in obj )
				dom[$_] = TEST.string( obj[$_] ) ? $B.eval( obj[$_] ) : $B.node( obj[$_] );
			return dom;
		};
		
		var $kill = IPC.Destroy = new function( obj ) {
			return delete obj;
		};
		
/*	creates a div with the class of IPCloader which has the little AJAX indicator in it 
	and appends it to the element you passed in or document.body	*/
		IPC.DOM.Loader = '<div class="IPCloader"></div>';
		IPC.Loader = Class.create();
		IPC.Loader.prototype = {
			initialize : function( element )
			{
				element = element || document.body;
				this.DOM = IPC.CreateDOM( IPC.DOM.Loader );
				
				this.element = $( element );
				if ( element != document.body )
					Element.setStyle( this.element, { position : 'relative' } );
					
				this.element.appendChild( this.DOM );
				Element.hide( this.DOM );
			}, 
			destroy : function() { 
				Element.setStyle( this.element, { overflow : 'visible' } );
				Element.remove( this.DOM ); 
			}, 
			hide : function() { 
				Element.setStyle( this.element, { overflow : 'visible' } );
				Element.hide( this.DOM ); 
			}, 
			show : function() { 
				Element.setStyle( this.element, { overflow : 'hidden' } );
				Element.show( this.DOM ); 
			}
		};
		
		IPC.Insertion = {
			Abstract : {
				initialize : function( element, insertPoint )
				{
					this.element = $( element ) || $B.eval( element );
					this.insertPoint = $( insertPoint );
					this.handleInsertion();
				}
			}, 
			After : Class.create(),
			Before : Class.create(),
			Bottom : Class.create(),
			Top : Class.create()
		};
		IPC.Insertion.After.prototype = Object.extend( {
			handleInsertion : function() {
				if ( this.insertPoint.nextSibling )
					this.insertPoint.parentNode.insertBefore( this.element, this.insertPoint.nextSibling );
				else
					this.insertPoint.parentNode.appendChild( this.element );
//					new IPC.Insertion.Bottom( this.element,  );
			}
		}, IPC.Insertion.Abstract );
		IPC.Insertion.Before.prototype = Object.extend( {
			handleInsertion : function() {
				this.insertPoint.parentNode.insertBefore( this.element, this.insertPoint );
			}
		}, IPC.Insertion.Abstract );
		IPC.Insertion.Bottom.prototype = Object.extend( {
			handleInsertion : function() {
				this.insertPoint.appendChild( this.element );
			}
		}, IPC.Insertion.Abstract );
		IPC.Insertion.Top.prototype = Object.extend( {
			handleInsertion : function() {
				this.insertPoint.insertBefore( this.element, this.insertPoint.firstChild );
			}
		}, IPC.Insertion.Abstract );
		
/*	Unique ID - Will only assign one if you specify and not on any object that doesn't have an ID
	use $UID.create();	*/
		IPC.UniqueID = Class.create();
		IPC.UniqueID.prototype = {
			NAMESPACE : 'IPCsys__', 
			initialize : function( namespace ) {
				this.ns = namespace || this.NAMESPACE;
				this.count = 0;
			}, 
			create : function()
			{
				var uid = this.ns + this.count;
				this.count++;
				return uid;
			}
		}
		var $UID = new IPC.UniqueID();

		
/*	use this to have a fancy scroll effect for anchor links on the same page	*/
		IPC.ScrollTo = Class.create();
		IPC.ScrollTo.prototype = {
			initialize : function( obj )
			{
				if ( obj instanceof Array ) {
					obj.each( this.initialize );
					return;
				}
				
				obj.getElementsBySelector( 'a[href^="#"]' ).each( function( a )
				{
					var place = a.href.replace( /^.*?#(.*)$/, "$1" );
					Event.observe( a, 'click', function( evt ) {
						new Effect.ScrollTo( $$( 'a[name="' + place + '"]' )[0] );
						Event.stop( evt );
					}, false );
				} );
			}
		};
		
		IPC.Interlace = Class.create();
		IPC.Interlace.prototype = {
			initialize : function( container, options ) { 
				this.CONTAINER = $( container );
				this.options = $H( {
					evenClass : 'even', 
					oddClass : 'odd',
					rule : 'tr', 
					iterator : function( node, i ) {
						return node.addClassName( ( i % 2 == 0 ? this.options.evenClass : this.options.oddClass ) );
					}
				} ).merge( options || {} );
				this.formatUI();
			}, 
			formatUI : function() {
				this.nodes = this.CONTAINER.getElementsBySelector( this.options.rule ).map( this.options.iterator.bind( this ) );
				return this.nodes;
			}, 
			reset : function() {
				return this.nodes.map( this._resetNode.bind( this ) );
			}, 
			_resetNode : function( node ) {
				return node.removeClassName( this.options.evenClass ).removeClassName( this.options.oddClass );
			}
		};
