/**
 * @name Proxicom JavaScript Toolkit
 * @overview A set of utlities that facilitate the loading of modules and code debugging.
 * @author Larry Root
 * @version 1.0
 */

/**
 * The root toolkit object.
 */
 
var prxm = {
	
	/** Show debug messages. 
	 * @type {Boolean}
	 */
	debug:false,
	
	/** 
	 * The file name of this script file. 
	 * @type {String}
	 */
	scriptName: "prxm.js",
	
	/** 
	 * They version of this toolkit.
	 * @type {String}
	 */
	version: "1.0",
	
	/** 
	 * Is the console object available.
	 * @type {Boolean}  
	 */
	hasConsole: (typeof console !='undefined'),
	
	/** 
	 * Name spaces of successfully loaded modules.
	 * @type {Array}
	 */
	modulesCreated: [],
	
	/**
	 * Loads a JavaScript module based on the provided name space. The namespace
	 * is a dot delimited string wich is translated into a directory path. Example: 
	 * foo.bar.baz -> foo/bar/baz.js 
	 * The namespace path starts relative to the prxm.js file.
	 * @param {String} namespace The namespace of the package to load. Example: "foo.bar.baz"
	 */
	load: function ( namespace ) {
		var filePath = prxm.getScriptPath() + namespace.gsub(".", "/") + '.js';
		if (prxm.modulesCreated.indexOf(namespace) == -1) {
			new Ajax.Request(filePath, {
				asynchronous: false,
				method: "get",
				onFailure: function(transport) { prxm.error("prxm.load FAILED :: "+transport.status+" "+filePath); },
				onException: function(transport, excp) { prxm.error("prxm.load EXCEPTION :: "+excp); },
				onSuccess: function() {			
					//Give the page some breathing room to apply the loaded script file before we check it
					setTimeout(function() {
						if (prxm.modulesCreated.indexOf(namespace) != -1) {
							prxm.info("prxm.load SUCCESS :: "+namespace);
						} else {
							prxm.error("prxm.load FAILED :: Failed to load "+namespace+". Possibly missing the prxm.create('"+namespace+"') statement in file "+filePath+".");
						}  
					}, 1);
				}
			});
		} else {
			prxm.info("prxm.load REDUNDANT :: ["+namespace+"] ");
		}
	},
	
	/**
	 * Returns the full URL of the Proxicom toolkit script minus the script name.
	 * @return {String} The full URL of the Proxicom toolkit script minus the script name
	 */
	getScriptPath: function () {
		if( prxm.scriptPath ) {
			return prxm.scriptPath;
		} else { 
			prxm.scriptPath = null;
		}
		
		prxm.scriptPath = $$('script[src*="'+prxm.scriptName+'"]')[0].readAttribute('src');
		prxm.scriptPath = prxm.scriptPath.substring(0, prxm.scriptPath.lastIndexOf( prxm.scriptName ));
		return  prxm.scriptPath;
		
	},
	
	/**
	 * Creates an object hierarchy within the global scope based on the provided
	 * object path.
	 * @param {String} objectPath The object hierarchy to create. Example "foo.bar.baz"
	 */
	create: function (objectPath) {
		var objPath = "";
		var objNames = objectPath.split('.');
		objNames.each(function(objName) {
			var newObjPath = objPath;
			newObjPath += (objPath=="") ? objName : "."+objName;  
			if ( eval("typeof("+newObjPath+")=='undefined'") ) {
				eval( newObjPath +"={};" );
			} else if (eval("typeof("+newObjPath+")=='object'" && objPath != "") ) {
				eval( objPath +".prototype."+objName+"={};" );
			} else if (eval("typeof("+newObjPath+")!='undefined'" && eval("typeof("+newObjPath+")!='object'") ) ) {
				prxm.error('prxm.create FAILED :: A non "object" value was found in the object path. Tried to create: '+namespace+' but was blocked at: '+newObjPath);
				return null;
			}
			objPath = newObjPath;
		});
		prxm.modulesCreated.push(objectPath);
	},
	
	/**
	 * Writes the provided objects properties and methods to the console.
	 * @param {Object} dumpObj The object to output.
	 */
	dumpObj: function (dumpObj) {
		if (dumpObj==null) {
			prxm.log("[dump object]: NULL");
		} else if (typeof(dumpObj)!= 'object') {
			prxm.log("[dump object]: "+dumpObj);
		} else {
			for (element in dumpObj) {
				if (dumpObj[element]==null) {
					prxm.log(element + ": NULL");
				} else if (dumpObj[element].inspect) {
					prxm.log(element + ": " + dumpObj[element].inspect() );
				} else {
					prxm.log(element + ": " + dumpObj[element].toString() );
				}
			}				
		}
	},
	
	/**
	 * Send a message to the console via the info method.
	 * @param {String} msg The message to output.
	 */
	info: function (msg) {
		if (prxm.hasConsole && prxm.debug) {
			console.info(msg);
		}	
	},
	
	/**
	 * Send a message to the console via the log method.
	 * @param {String} msg The message to output.
	 */
	log: function (msg) {
		if (prxm.hasConsole && prxm.debug) {
			console.log(msg);
		}
	},
	
	/**
	 * Send a message to the console via the error method.
	 * @param {String} msg The message to output.
	 */
	error: function (msg) {
		if (prxm.debug) {
			if (prxm.hasConsole) {
				console.error(msg);	
			} else {
				alert(msg);
			}
		}
	},
	/**
	 * Notify developer that the given function has been deprecated.
	 * @param {Object} funcName The name of the function/method that has been depricated. Use full object paths.
	 * @param {Object} description An explaination of why the function/method has been deprecated and alternatives to it.
	 */
	deprecated: function (funcName, description) {
		var msg = funcName+" is Deprecated! "+description;
		if (prxm.hasConsole && prxm.debug) {
			console.error(msg);
		}
	}	
}