/*
	For non-Mozilla products that do not have a for Each method of the Array object.
	This needs to be replaced with... http://dean.edwards.name/weblog/2006/07/enum/
	As to allow for enumeration of OBJECTS and not just array items
*/
if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function( fun /*, thisp*/ )
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

var $core =
{
	newViewInstance: function( view )
	{
		$core[ view ] =
		{
			methods:	[],
			variables:	{},
			images:		[],
			scripts:	[]
		};
	},
	register:function( type, init, params )
	{
		
		switch( type )
		{
			case "onload":
				var objType = "methods";
			break;
			case "variable":
				var objType = "variables";
			break;
			case "script":
				var objType = "scripts";
			break;
			case "image":
				var objType = "images";
			break;
		}

		if( typeof( params ) == "string" )	params = new Array( params );
		if( typeof( init ) == "string" )	init = new Array( init );

		if( typeof( params ) == "array" || typeof( params ) == "object" )
		{
			params.forEach( function( param, index, array ) 
			{
				if( typeof( init ) == "array" || typeof( init ) == "object" )
				{
					init.forEach( function( item, index, array ) 
					{
						$core.registerItem( objType, item, param );
					});
				}
			});
		}
	},
	
	isRegistered:function( initObject, param )
	{
		var isRegistered = false;
		initObject.forEach( function( item, index, array )
		{
			if ( item == param )
			{
				isRegistered = true;
			}
		});
		return isRegistered;
	},
	
	registerItem:function( objType, init, param )
	{
		var slug = false;

		if( init.indexOf( ":" ) != -1 )
		{
			var initParams = init.split( ":" );
			init = initParams[ 0 ];
			slug = initParams[ 1 ];
		}

		/*quick fix but this should be tested a bit better*/
		if( slug != false && document.location.toString().indexOf( slug ) == -1 )
		{
			return false;
		}
		
		if( !$core[ init ] )
		{
			$core.newViewInstance( init );
		}
		
		var isRegistered = $core.isRegistered( $core[ init ][ objType ], param );
		
		if( !isRegistered )
		{
			$core[ init ][ objType ].push( param );
		}
		return true;
	},
	
	all:{
		methods:[],
		variables:{},
		scripts:[
			"jquery.livequery.js",
			"jquery.query.js",
			"scrolly.js",
			"utilities.js",
			"jquery.pngFix.pack.js",
			"jquery.cookie.js",
			"/inc/scripts/fonts.js"
		],
		images:[],
		callback:function()
		{
			if( $.browser.msie )
			{
				$(document).pngFix(); 
			}
		}
	}
};

var $local = 
{
	cache:{},
	loaded:
	{
		params:			false,
		scriptChains:	false
	}
};

var $init =
{
	params:	{},
	
	log: function( message )
	{
		if( $( "body" ).hasClass( "debug" ) )
		{
			try
			{
				console.log( message );
			}
			catch( er )
			{
				//Console is not defined.
				//alert( message );
			}
		}
	},
	
	run: function()
	{
		$init.params.levels[ $init.params.level ]();
	},
	
	destroy: function()
	{
		return delete( $init.params );
	},
	
	complete: function( initLevel )
	{
		$init.log( initLevel, "Complete" )
		$init.params.levels.forEach(function( init )
		{
			if( init == initLevel )
			{
				if( $init.params.levels.length == $init.params.level )
				{
					return $init.destroy();
				}
				$init.params.level++;
				$init.run();
				return true;
			}
		});
		return false;
	},
	
	launch: function( params )
	{
		$init.params.settings			= params;
		$init.params.inits				= [ $core.all ];
		$init.params.callbacks			= [];
		$init.params.level				= 0;
		$init.params.levels				= [ $init.scripts, $init.methods, $init.images, $init.callback ];
		$init.params.sourcePath			= "/templates/cba_cloud/scripts/";
		$init.params.initIndex			= 0;
		$init.params.unitIndex			= 0;
		$init.params.scriptHashTable	= [];
		$init.params.timeout			= 30000; // 30 Seconds
		$init.params.globalTime			= 0;
		
		if( !$core[ $init.params.settings.view ] )
		{
			$core.newViewInstance( $init.params.settings.view );
		}
		$init.params.inits.push( $core[ $init.params.settings.view ] );
		$init.log( "Starting Main INIT\n" );
		$init.run();
	},
	
	scripts: function(){
		$init.log( $init.params );
		$init.params.inits.forEach( function( unit, unitIndex )
		{
			if( unit.scripts.length > 0 )
			{
				$init.params.unitIndex = unitIndex;
				$init.params.scriptHashTable[ $init.params.unitIndex ] = new Array();
				
				unit.scripts.forEach(function( element, index, array )
				{
					$init.params.scriptHashTable[ $init.params.unitIndex ][ index ] = 
					{
						loaded		: false,
						callback	: null
					};
					
					if( element.charAt( 0 ) == "/" )
					{
						var srcPath = element;
					}
					else
					{
						var srcPath = $init.params.sourcePath + element;
					}
					
					$init.log( "Getting Script: " + srcPath );
					$.getScript( srcPath, function( data )
					{
						
						$init.params.scriptHashTable[ $init.params.unitIndex ][ index ].loaded = true;
						var callbackMethod = $init.params.scriptHashTable[ $init.params.unitIndex ][ index ].callback; 
						
						if( typeof( callbackMethod ) == "function" )
						{
							callbackMethod( $init.params.settings );
						}
					});
				});
			}
		});
		
		$init.params.checkInterval = window.setInterval( function()
		{
			$init.params.globalTime	+= 100;
			
			if( $init.params.globalTime >= $init.params.timeout )
			{
				$init.log( "TIMEOUT SCRIPT INIT" );
				$init.clearCheck();
			}
			
			if( $init.scriptCheck() )
			{
				$init.clearCheck();
				$init.complete( $init.scripts );
			}
			
		}, 100 );
	},
	
	clearCheck:function()
	{
		window.clearInterval( $init.params.checkInterval );
	},
	
	scriptCheck: function()
	{
		$init.params.scriptHashTable.forEach( function( item, index, list )
		{
			
			item.forEach(function( element )
			{
				$init.log( element );
				if( element.loaded != true )
				{
					passed = false;
					return false;
				}
				else
				{
					passed = true;
				}
			});
			if( !passed )
			{
				return false;
			}
		});
		if( passed )
		{
			return true;
		}
	},
	
	methods: function()
	{
		$init.log( "Starting Methods INIT\n" );
		//iterate inits chain and call all methods in cha in.
		$init.params.inits.forEach( function( unit )
		{
			unit.methods.forEach( function( element, index )
			{
				$init.methodExec( element );
			});
			( unit.callback ) ? $init.params.callbacks.push( unit.callback ) : null;
		});
		$init.complete( $init.methods );
	},
	
	images: function( image )
	{
		$init.params.inits.forEach( function( unit )
		{
			unit.images.forEach( function( element )
			{
				$local.cache[ element ] = new Image();
				$local.cache[ element ].src = element;
			});
		});
		$init.complete( $init.images );
	},
	
	callback: function()
	{
		$init.log( "Starting callback INIT\n" );
	},
	
	methodExec:function( element, errorcount )
	{
		var initError = false;

		switch( typeof( element ) )
		{
			case "string":
				if( typeof( window[ element ] ) == "function" )
				{
					try
					{
						window[ element ]( $local.loaded.params );
					}
					catch( er )
					{
						//Pass back fail
					}
				}
				else
				{
					if( !errorcount ) errorcount = 0;
					if( errorcount > 10 )
					{
						try{
						console.log( "TRIED 10 TIMES and FAILED!!!!" );
						}catch(er){}
					}
					else
					{
						window.setTimeout( function(){
							$init.methodExec( element, errorcount++ );
						},500 );
					}
					initError =  "Method init failed. Method does not exist\nValue: " + element;
				}
			break;
			case "function":
				try
				{
					element( $local.loaded.params );
				}
				catch( er )
				{
					//Pass back fail
				}
			break;
			default:
				
				if( !errorcount ) errorcount = 0;
				if( errorcount > 10 )
				{
					try{
					console.log( "TRIED 10 TIMES and FAILED!!!!" );
					}catch(er){}
				}
				else
				{
					window.setTimeout( function(){
						$init.methodExec( element, errorcount++ );
					},500 );
				}
				//initError = "Method init type not accecpted\nType: " + typeof( element ) + "\nValue: " + element;
			break;
		}
		
		if( initError )
		{
			//throw new Error( initError );
		}
	}
};

$(function()
{
	$init.launch( params );
});

