/*
####################################################################################################
# JS CORE CLASS
# Version: 1.0.1 | Last Update: 06 August 2009 | Created On: 30 July 2009
####################################################################################################
# Copyright (C) by E-Muze (www.E-Muze.net)
# Copying the content of this file or fragments of this file's content with individual 
# functionality is strictly forbidden without the written consent of the author. Using this code
# as an example in order to understand and learn from it, with the purpose of improving your own
# work and/or writing your own code with similar functionality, is allowed and encouraged.
####################################################################################################
# CHANGELOG:
# v1.0.0 (30 July 2009)
#	- Class created.
# v1.0.1 (06 August 2009)
#	- Fixed implementation of custom callback on getRemoteContentCallback method.
####################################################################################################
# DOCUMENTATION:
# >> This class is a collection of engine-related functions that are not complex enough to be
# incorporated within their own class. The core class is included and instanced only once, under
# the object name "core", and should be made available on all website pages.
# >> The CFG property object holds the configuration parameters made available to the javascript
# environment by the server-side script (by the site engine).
####################################################################################################
*/

function jsCore (CFG)
{
	//----------------------------------------------------------------------------------------------
	// OBJECT PROPERTIES
	
	var self = this; // bind reference to self
	
	self.windowLoaded = false; // flag to determine if the current window has finished loading
	
	self.loader = null; // reference to local httpBus object
	self.loaderCCB = null; // stores custom callback (CCB) used with the loader operations
	
	self.MEM = new Array (); // local storage container for various internally used values
	
	//----------------------------------------------------------------------------------------------
	// DEFAULT CONFIG
	
	self.CFG = 
	{
		DOMAIN : null,
		URL_ROOT : null,
		CONTENT_URL : null,
		URL_FORMAT : null,
		WEBSITE_NAME : null,
		
		JS_ERROR_REPORT : 3
	};
	
	//----------------------------------------------------------------------------------------------
	// OBJECT INIT
	
	self.init = function (CFG)
	{
		// load configuration params
		self.loadConfig (CFG);
		
		// set onload event listener on window (note that, IE will trigger this event after triggering the body onload, and Firefox will trigger it before the body onload)
		self.bindEvent ('load', window, self.windowLoadedEvent);
	};
	
	//----------------------------------------------------------------------------------------------
	// WINDOW LOADED EVENT METHOD
	
	self.windowLoadedEvent = function ()
	{
		// clear window onload event
		self.clearEvent ('load', window, self.windowLoadedEvent);
		
		// set windowLoaded flag
		self.windowLoaded = true;
	};
	
	//----------------------------------------------------------------------------------------------
	// BIND EVENT METHOD

	self.bindEvent = function (event, obj, callback, capturePhase)
	{
		if (!obj) return false;
		capturePhase = capturePhase ? true : false;
		
		if (obj.addEventListener) obj.addEventListener (event, callback, capturePhase);
		else if (obj.attachEvent) obj.attachEvent ('on' + event, callback);
		else return false;
		
		return true;
	}

	//----------------------------------------------------------------------------------------------
	// CLEAR EVENT METHOD

	self.clearEvent = function (event, obj, callback, capturePhase)
	{
		if (!obj) return false;
		capturePhase = capturePhase ? true : false;
		
		if (obj.removeEventListener) obj.removeEventListener (event, callback, capturePhase);
		else if (obj.detachEvent) obj.detachEvent ('on' + event, callback);
		else return false;
		
		return true;
	}
	
	//----------------------------------------------------------------------------------------------
	// INIT LOADER METHOD
	
	/*
		Will check if httpBus class is available, and create a local instance within
		the .loader property, if httpBus is not available, .loader will be made null
	*/
	
	self.initLoader = function ()
	{
		// try to init loader object
		if (!self.loader)
		{
			if (httpBus)
				self.loader = new httpBus ('core.loader', {callback : self.loaderCallback});
			else
			{
				self.throwError ('jsCore', 'cannont initialize loader, httpBus class is not available');
				return false;
			}
		}
		
		// if loader is usable
		if (self.loader.usable)
		{
			// if loader is busy, cancel previous operation
			if (self.loader.busy) self.loader.cancel ();
			
			// if loader is still busy, fail with error
			if (self.loader.busy)
			{
				self.throwError ('jsCore', 'loader is stuck in busy mode');
				return false;
			}
			
			// return init success
			return true;
		}
		// else, init failure
		else return false;
	};
	
	//----------------------------------------------------------------------------------------------
	// LOAD FROM URL METHOD
	
	self.loadFromURL = function (fromURL, AUX, customCallback, modifiedSince)
	{
		// if loader init successful
		if (self.initLoader ())
		{
			// store callback
			self.loaderCCB = customCallback;
			
			// start load operation
			self.loader.getURL (fromURL, modifiedSince, {op: 'loadFromURL'});
			
			// return init success
			return true;
		}
		// else, init failure
		else return false;
	};
	
	//----------------------------------------------------------------------------------------------
	// GET REMOTE CONTENT METHOD
	
	self.getRemoteContent = function (fromURL, destEnt, loadBar, customCallback, modifiedSince)
	{
		// fail if loader not ready
		if (!self.initLoader ())
			return false;
		
		// set mem data for this method
		self.MEM['getRemoteContent'] =
		{
			destEnt : destEnt,
			loadBar : loadBar,
			callback : customCallback
		};
		
		// issue load from URL request
		if (self.loadFromURL (fromURL, null, self.getRemoteContentCallback, modifiedSince))
		{
			// if we have a load bar, display it
			if (loadBar) loadBar.style.display = '';
		}
		
		// return success
		return true;
	};
	
	//----------------------------------------------------------------------------------------------
	// GET REMOTE CONTENT CALLBACK METHOD
	
	self.getRemoteContentCallback = function (myBus)
	{
		var content = '';
		if (myBus.outcome[0] == 'success' && myBus.returnData.text)
			content = myBus.returnData.text;
		
		var thisMem = self.MEM['getRemoteContent'];
		
		// if destination entity exists
		if (thisMem.destEnt)
		{
			// if destination entitity is an object that supports this method's return
			if (thisMem.destEnt.gotRemoteContent)
				thisMem.destEnt.gotRemoteContent (myBus.returnData.text);
			// else, if destination entity is a html element
			else if (thisMem.destEnt.parentNode)
			{
				// write content inside it and make sure it's visible
				thisMem.destEnt.innerHTML = myBus.returnData.text;
				thisMem.destEnt.style.display = '';
			}
			
			// if load bar is set, hide it
			if (thisMem.loadBar)
				thisMem.loadBar.style.display = 'none';
		}
		
		// call custom callback
		if (thisMem.callback)
			thisMem.callback (myBus);
	};
	
	//----------------------------------------------------------------------------------------------
	// LOADER CALLBACK METHOD
	
	self.loaderCallback = function (myBus)
	{
		// if loader outcome is success
		if (myBus.outcome[0] == 'success')
		{
			// handle operation
			if (myBus.auxData.op == 'loadFromURL')
			{
				// does nothing
			}
			// handle other operations
			else if (myBus.auxData.op == 'other')
			{
				// does nothing
			}
		}
		
		// call callback, if set
		if (self.loaderCCB)
			self.loaderCCB (myBus);
	};
	
	//----------------------------------------------------------------------------------------------
	// THROW ERROR METHOD
	
	/*
		Level zero errors are considered critical, the importance of the error decreases as
		the level increases.
	*/
	
	self.throwError = function (source, message, level)
	{
		// make sure level is integer
		level = parseInt (level);
		
		// compose error output
		var errOut = 'Level ' + ((level > 0) ? level : 0) + ' javascript error in [' + source + ']:\n' + (message ? message : 'no error message');
		
		// output error if lower than set level
		if (level < CFG.JS_ERROR_REPORT) alert (errOut);
	};
	
	//----------------------------------------------------------------------------------------------
	// TO STRING METHOD

	self.toString = function (event, obj, callback, capturePhase)
	{
		var OUT = 'Core CFG:\n\n';
	    for (var prop in CFG)
			eval ('if (CFG.' + prop + ' === 0 || (CFG.' + prop + ' && CFG.' + prop + ' != undefined)) OUT += \'' + prop + ' : \' + CFG.' + prop + " + '\\n';");
		
		return OUT;
	}
	
	//----------------------------------------------------------------------------------------------
	// LOAD CONFIG METHOD
	
	/*
		This method loads the configuration parameters from the given configuration array and
		uses defaults where values are not set.
	*/
	
	self.loadConfig = function (CFG)
	{
		if (!CFG) return null;
	    for (var prop in CFG)
			eval ('self.CFG.' + prop + ' = (CFG.' + prop + ' === 0 || (CFG.' + prop + ' && CFG.' + prop + ' != undefined)) ? CFG.' + prop + ' : self.CFG.' + prop + ';');
	};
	
	//----------------------------------------------------------------------------------------------
	// INIT THE OBJECT AUTOMATICALLY
	
	self.init (CFG);
}
	
/*
####################################################################################################
*/
