/**
 * @fileOverview 
 *
 * TouTouJS is a javascript framework which provides a cross-browser toolkit and advanced 
 * and interactive GUI objects. It is designed to be used in either simple or complex 
 * web sites, applications and back offices (web 2.0, Ajax, DHTML and CSS extension, etc.). 
 * 
 * TouTouJS is freely distributable under the terms of the GNU Lesser General Public Licence (LGPL).
 * For more details, see: http://www.gnu.org/licenses/lgpl.html
 * 
 * @author dev@toutoujs.org (http://www.toutoujs.org)
 * @version 0.1.3 alpha
 */



if (typeof toutou == "undefined") {


/**
 * This is the main global object.
 * @class toutou
 */
var toutou = new function() {
	/**
	 * List of modules which have been loaded with the "require" method. 
	 * @private 
	 */
	this.loadedModules = {};
};


/**
 * The main configuration object
 * @class
 */
toutou.config = new function() {
	/** 
	 * Default debug level.
	 * <br>
	 * The possible values are : ALL, VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL, NONE
	 * @type String
	 */
	this.debugLevel = "WARNING";

	/** 
	 * Debug console position ("top" or "bottom") 
	 * @type String
	 */
	this.debugConsolePosition = "top"; // 'top' or 'bottom'

	/** 
	 * The relative or absolute url of TouTouJS modules
	 * @type String
	 */
	this.rootUrl = "";

	/** 
	 * Root urls for extra javascript modules
	 * @type Object (hash)
	 */
	this.extraRootUrls = {};

	/** 
	 * Url of the wrapper for the "require" function (e.g. "/js/toutou/require.php")
	 * @type String
	 */
	this.requireWrapper = "";
};


/**
 * require
 */
toutou.require = function(/*String+*/) {
	var modulesToLoadWithWrapper = new Array();
	
	for (var argumentCounter=0; argumentCounter<arguments.length; argumentCounter++) {
		var newModuleName = arguments[argumentCounter];
		
		toutou.debugLogger.log("VERBOSE","Require " + newModuleName);
		if(!newModuleName){ continue; }

		// check if module is already loaded
		if (this.loadedModules[newModuleName]) {
			continue;
		}

		// create intermediate objects if necessary
		var p = newModuleName.split('.');
		var parentModule = window;
		for (var i=0; i<p.length; i++) {
			var subModuleName = p[i];
			if (!parentModule[subModuleName]) {
				parentModule[subModuleName] = {};
			}
			parentModule = parentModule[subModuleName];
		}

		// set rootUrl
		var p = newModuleName.split(".");
		var rootUrl = this.config.extraRootUrls[p[0]];
		if (!rootUrl) { rootUrl = this.config.rootUrl; }

		// load module
		if (p[0] == "toutou" && this.config.requireWrapper) {
			modulesToLoadWithWrapper.push(newModuleName);
		}
		else {
			// convert periods to slashes
			var url = rootUrl + "/" + newModuleName.replace(/\./g, '/') + '.js';
			this.loader.loadUri(url);

			// update loaded modules
			this.loadedModules[newModuleName] = true;
		}
	}

	// load modules with wrapper
	if (this.config.requireWrapper && modulesToLoadWithWrapper.length>0) {
		// use external wrapper
		var url = this.config.requireWrapper;
		url+= "?Modules=" + modulesToLoadWithWrapper.join(":");
		var keys = new Array();
		for (var key in this.loadedModules) { keys.push(key); };
		url+= "&LoadedModules=" + keys.join(":");
		this.loader.loadUri(url);
	}
};


/**
 * _requireThroughWrapper
 * @ignore
 */
toutou._requireThroughWrapper = function(/*String*/ newModuleName) {
	toutou.debugLogger.log("VERBOSE","_requireThroughWrapper " + newModuleName);
	if(!newModuleName){ return; }

	// check if module is already loaded
	if (this.loadedModules[newModuleName]) {
		return true;
	}

	// create intermediate objects if necessary
	var p = newModuleName.split(".");
	var parentModule = window;
	for (var i=0; i<p.length; i++) {
		var subModuleName = p[i];
		if (!parentModule[subModuleName]) {
			parentModule[subModuleName] = {};
		}
		parentModule = parentModule[subModuleName];
	}

	// set rootUrl
	var p = newModuleName.split(".");
	var rootUrl = this.config.extraRootUrls[p[0]];
	if (!rootUrl) { rootUrl = this.config.rootUrl; }

	// convert periods to slashes
	var relpath = rootUrl + "/" + newModuleName.replace(/\./g, '/') + '.js';
	this.loader.loadUri(relpath);

	// update loaded modules
	this.loadedModules[newModuleName] = true;
};


/* 
 * addOnLoad
 */
toutou.addOnLoad = function(/*String|Function*/ functionName, /*Object?*/ obj) {
	if (obj) {
		this.addDOMLoadEvent(
			function() { obj[functionName](); }
		);
	} 
	else {
		this.addDOMLoadEvent(functionName);
	}
};


/* 
 * addDOMLoadEvent
 */
toutou.addDOMLoadEvent = function(func) {
/*
 * (c)2006 Dean Edwards/Matthias Miller/John Resig
 * Special thanks to Dan Webb's domready.js Prototype extension
 * and Simon Willison's addLoadEvent
 *
 * For more info, see:
 * http://dean.edwards.name/weblog/2006/06/again/
 * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
 * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
 * 
 * Thrown together by Jesse Skinner (http://www.thefutureoftheweb.com/)
 *
 *
 * To use: call addDOMLoadEvent one or more times with functions, ie:
 *
 *    function something() {
 *       // do something
 *    }
 *    addDOMLoadEvent(something);
 *
 *    addDOMLoadEvent(function() {
 *        // do other stuff
 *    });
 *
 */
	if (!window.__load_events) {
		var init = function () {
			// quit if this function has already been called
			if (arguments.callee.done) return;

			// flag this function so we don't do the same thing twice
			arguments.callee.done = true;

			// kill the timer
			if (window.__load_timer) {
				clearInterval(window.__load_timer);
				window.__load_timer = null;
			}

			// execute each function in the stack in the order they were added
			for (var i=0;i < window.__load_events.length;i++) {
				window.__load_events[i]();
			}
			window.__load_events = null;

			// clean up the __ie_onload event
			/*@cc_on @*/
			/*@if (@_win32)
				document.getElementById("__ie_onload").onreadystatechange = "";
			/*@end @*/
		};

		// for Mozilla/Opera9
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", init, false);
		}

		// for Internet Explorer
		/*@cc_on @*/
		/*@if (@_win32)
			document.write("<scr"+"ipt id=__ie_onload defer src=javascript:void(0)><\/scr"+"ipt>");
			var script = document.getElementById("__ie_onload");
			script.onreadystatechange = function() {
				if (this.readyState == "complete") {
					init(); // call the onload handler
				}
			};
		/*@end @*/

		// for Safari
		if (/WebKit/i.test(navigator.userAgent)) { // sniff
			window.__load_timer = setInterval(function() {
				if (/loaded|complete/.test(document.readyState)) {
					init(); // call the onload handler
				}
			}, 10);
		}

		// for other browsers
		window.onload = init;

		// create event function stack
		window.__load_events = [];
	}

	// add function to event stack
	window.__load_events.push(func);
};


/* 
 * extend
 */
toutou.extend = function(/*Object*/ object, /*Class*/ classToAdd) {
	if (!object) { 
		toutou.debugLogger.log("ERROR", "toutou.extend : Empty parameter 'object'");
		return;
	}
	if (!classToAdd) { 
		toutou.debugLogger.log("ERROR", "toutou.extend : Empty parameter 'classToAdd'");
		return;
	}
	var classPrototype = classToAdd.prototype;
	if (!classPrototype) { 
		toutou.debugLogger.log("ERROR", "toutou.extend : Class has no prototype");
		return;
	}
	for (var property in classPrototype) {
		object[property] = classPrototype[property];
	}
};


//************************************************************
// DEBUG_LOGGER
//************************************************************

/* 
 * @name debugLogger
 */
toutou.debugLogger = {
	LOG_LEVELS : Array(
		"ALL",
		"VERBOSE",
		"DEBUG",
		"INFO",
		"WARNING",
		"ERROR",
		"FATAL",
		"NONE"
	),
	
	currentDebugLevel :		0,
	isPageLoaded :			false,
	outputBuffer:			[]
};

/*
 * init
 */
for (var i=0; i<toutou.debugLogger.LOG_LEVELS.length; i++) {
	toutou.debugLogger["LOG_LEVEL_" + toutou.debugLogger.LOG_LEVELS[i]] = i;
}
 
/* 
 * setDebugLevel
 */
toutou.debugLogger.setDebugLevel = function (/*String*/ level) {
	this.currentDebugLevel = this["LOG_LEVEL_" + level] || 0;
};

/* 
 * log
 */
toutou.debugLogger.log = function (/*String*/ strLevel, /*String*/ message) {
	var level = this["LOG_LEVEL_" + strLevel] || 7;
	if (level < this.currentDebugLevel) { return; }
	this.outputBuffer.push("[" + strLevel + "] " + message);
	if (this.isPageLoaded) { this.printBuffer(); }
};

/* 
 * printBuffer
 */
toutou.debugLogger.printBuffer = function () {
	if (this.outputBuffer.length == 0) { return; }
	var console = document.getElementById("toutou_DebugConsole");
	if(!console) { 
		var console = document.createElement("div");
		console.id = "toutou_DebugConsole";
		console.style.border = "1px solid #900000";
		console.style.backgroundColor = "#FFFF99";
		console.style.color = "#000077";
		console.style.fontFamily = "Arial";
		console.style.fontSize = "12px";
		console.style.padding = "5px 10px 5px 10px";
		console.style.margin = "3px 3px 10px 3px";
		console.style.textAlign = "left";
		if (toutou.config.debugConsolePosition == "bottom") {
			document.body.appendChild(console);
		}
		else {
			document.body.insertBefore(console, document.body.firstChild)
		}
	}

	while(this.outputBuffer.length > 0) {
		var div = document.createElement("div");
		div.appendChild(document.createTextNode(this.outputBuffer.shift()));
		console.appendChild(div);
	}
};


//************************************************************
// LOADER
//************************************************************

/**
 * These loader methods are only to be used in this file 
 * @ignore
 */
toutou.loader = {
	//loadedUris: Array()
};

/* 
 * loadUri
 */
toutou.loader.loadUri = function(/*String*/ uri){
	var http = this.getXmlHttpObject();
	try {
		http.open("GET", uri, false);
		http.send(null);
	} catch (e) {
		toutou.debugLogger.log("WARNING","Ajax request failed (" + uri + "): " + e.name + ', ' + e.message);
		return false;
	}

	var contents = http.responseText;
	if(!contents){ 
		return false; 
	}

	try {
		window.eval(contents);
	} catch (e) {
		toutou.debugLogger.log("WARNING","Javascript evaluation of ajax response failed (" + uri + ") " + e);
	}

	return true;
};


/* 
 * getXmlHttpObject
 */
toutou.loader.getXmlHttpObject = function() {
	var xmlHttp = null;
	try {
		// Firefox, Opera 8.0+, Safari
		xmlHttp = new XMLHttpRequest();
	}
	catch (e) {
		// Internet Explorer
		try {
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;
};


//************************************************************
// INIT
//************************************************************
toutou.debugLogger.setDebugLevel(toutou.config.debugLevel);
toutou.addOnLoad( 
	function() {
		toutou.debugLogger.isPageLoaded = true;
		toutou.debugLogger.printBuffer();
	}
);


	
}
		toutou.config.rootUrl = '/GBjs/toutou_unpacked';
		toutou.config.requireWrapper = '/GBjs/toutou_unpacked/toutou/require.php';
	