/**
 * @projectDescription
 * @author Nicolas Deveaud
 * @version 1.1
 */

if(typeof documentAddonLoader != 'undefined')
	throw(new Error('Script documentAddonsLoader chargé deux fois, ou en conflit avec un autre script'));

var documentAddonLoader = (function() {
	// URL racine d'où charger les fichiers
	var _ROOT_ = (function() {
			var scripts = document.getElementsByTagName('script');
			var regex = /^(.*)documentAddonsLoader(IE)?\.js(\?.*)?$/;
			var matches = false;
			for(var i = 0; i < scripts.length; i++) {
				if((matches = regex.exec(scripts[i].src))) {
					return matches[1];
				}
			}
			return '';
		})();

	// Déclaration de la classe DocumentAddon
	var DocumentAddon = (function() {
	// Propriétés privées statiques

		// Config par défaut
		var defaultConfig = {
			 name: 			null
			,injectPage:	null
			,injectNode:	'body'
			,injectMode:	'append'
			,html:			true
			,js:			true
			,css:			true
		};

	// Constructeur (qui contient la déclaration des propriétés et méthodes)
		return function(cfg) {
		// propriétés privées

			// extension de la propriété config avec les valeurs par défaut
			var config = jQuery.extend({}, defaultConfig, cfg);

			// Si aucun nom d'addon n'est fourni, on stop tout de suite
			if(typeof config.name != 'string' || config.name.length < 1) {
				return;
			}

			var _scop = this;
			var cssLoaded = [];
			var _ADDON_PATH_ = _ROOT_+config.name+'/';

			// Si la page actuelle ne correspond pas à la page d'injection, on stop tout de suite
			if(config.injectPage) {
				if(config.injectPage.constructor == RegExp &&
				   !config.injectPage.test(window.location.toString()))
					return;
				else if(typeof config.injectPage == 'string' &&
				   config.injectPage != window.location.toString())
					return;
			}

			// Si le noeud cible de l'addon n'est pas présent, on stop tout de suite
			if(jQuery.isReady && jQuery(config.injectNode).length == 0) {
				return;
			}

		// méthodes privée

			var loadCss = function(url) {
				url = (typeof url == 'string') ? url : _ADDON_PATH_+'style.css';
				if(typeof cssLoaded[url] != 'undefined')
					return;
				cssLoaded[url] = false;
				(function() {
					var link = document.createElement('link');
					link.rel = 'stylesheet';
					link.type = 'text/css';
					link.href = url;

					var head = document.getElementsByTagName('HEAD');
					if(!head)
						throw(new Error('Aucune balise head dans le document HTML'));
					head[0].appendChild(link);
				})();
				cssLoaded[url] = true;

				if(typeof onCssLoaded == 'function')
					onCssLoaded(url);
			};

			var injectHtml = function() {
				if(!html)
					return;
				jQuery(config.injectNode).each(function() {
					var node = jQuery(html);
					if(node.length > 1)
						node = jQuery('<div/>').append(node);
					htmlNodes = htmlNodes ? htmlNodes.add(node) : node;
					switch(config.injectMode) {
						case 'before':
							$(this).before(node);
							break;
						case 'after':
							$(this).after(node);
							break;
						case 'prepend':
							$(this).prepend(node);
							break;
						case 'replace':
							$(this).after(node).remove();
							break;
						default:
							$(this).append(node);
							break;
					}
				});
				if(typeof onHtmlInjected == 'function') {
					onHtmlInjected();
				}
			};


		// méthodes publiques

			this.onWindowLoaded = function() {
				if(config.css) {
					try { loadCss(); }
					catch(e) {}
				}
				if(config.html) {
					try { injectHtml(); }
					catch(e) {}
				}
			};


		// méthodes privées surchargeables

			var onHtmlInjected = function() {
				if((typeof jsLoadError != 'undefined') && htmlNodes) {
					htmlNodes.append('<div class="error">gestion des interactions non activée</div><!-- '+jsLoadError.toString()+' -->');
				}
			};

			var onCssLoaded = function() {};


			if(config.html) {
				try {
					var html = ajax_get(_ADDON_PATH_+'content.php')
						.replace(/_ADDON_PATH_/g, _ADDON_PATH_)
						.replace(/_ROOT_/g, _ROOT_);
					var htmlNodes;
				} catch(e) {
					config.html = false;
				}
			}

			if(config.js) {
				try {
					var js = ajax_get(_ADDON_PATH_+'javascript.js');
					eval(js);
				} catch(e) {
					var jsLoadError = e;
				}
			}

			if((typeof DOMReady == 'undefined' && jQuery.isReady) || DOMReady()) {
				_scop.onWindowLoaded();
			} else {
				if(jQuery.browser.msie) {
					(function() {
						var wait = function() {
							if(wait.count++ > 1000) {
								return;
							}
							var loadOK = false;
							if(typeof DOMReady == 'undefined') {
								if(!jQuery.isReady)
									window.setTimeout(wait, 10);
								else
									loadOK = true;
							} else if(!DOMReady()) {
								window.setTimeout(wait, 10);
							} else
								loadOK = true;

							if(loadOK) {
								_scop.onWindowLoaded();
							}
						};
						wait.count = 0;
						wait();
					})();
				} else {
					jQuery(function() {
						if(typeof _scop.onWindowLoaded == 'function')
							_scop.onWindowLoaded();
					});
				}
			}
		};
	})();

	var execConfigFile = function(configFile) {
		if(typeof configFile != 'string')
			configFile = _ROOT_+'config.js';

		// Chargement de la configuration des addons à mettre en place.
		try {
			var config = eval(ajax_get(configFile));
		} catch(e) {
			var config = [];
		}

		execConfig(config);
	};

	var execConfig = function(config) {
		if(config.constructor != Array)
			config = [];

		// Pour chaque conf, charger l'addon.
		for(var i = 0; i < config.length; i++) {
			new DocumentAddon(config[i]);
		}
	};

	var ajax_get = function(url) {
		var xhr = jQuery.ajax({
				url:	url,
				async:	false
			});
		if(xhr.readyState != 4)
			throw(new Error('Echec de chargement synchrone de '+url));
		if(xhr.status != 200) {
			throw(new Error('Document introuvable : '+url));
		}
		return xhr.responseText;
	};

	// si jQuery est déjà chargé, on lance execConfigFile
	if(typeof jQuery == 'function') {
		execConfigFile();
	} else {
		// jQuery non chargé : On va le charger avant de lancer execConfigFile
		/*
			Etant donné que l'on charge jQuery en ajax, le DOM sera peut-être déjà chargé pour la
			suite de notre script, et donc l'évenement document.ready ne se déclenchera plus. Pour
			éviter des problèmes, on met un observer sur le chargement de la page et on renseignera
			un controleur "DOMReady" qui nous permettra de verifier si window est ou non déjà chargé
			quand on le souhaitera.
		*/
		var DOMReady = (function() {
			var ready = false;
			var get = function() {
				return ready;
			};
			get.set = function() {
				ready = true;
			};
			return get;
		})();

		/* for Mozilla/Opera9 */
		if (document.addEventListener) {
			document.addEventListener('DOMContentLoaded', DOMReady.set, false);
		}

		/* for Internet Explorer */
		/*@cc_on @*/
		/*@if (@_win32)
			document.write('<script id="__ie_onload" defer src="javascript:void(0)"><\/script>');
			document.getElementById('__ie_onload').onreadystatechange = function() {
				if (this.readyState == 'complete')
					DOMReady.set();
			};
		/*@end @*/

		/* for Safari */
		if (/WebKit/i.test(navigator.userAgent)) { // sniff
			(function() {
				var _timer = setInterval(function() {
					if (/loaded|complete/.test(document.readyState)) {
						DOMReady.set();
						window.clearInterval(_timer);
					}
			  	}, 10);
			})();
		}

		/* for other browsers */
		if(typeof window.onload != 'function')
			window.onload = function() {
				DOMReady.set();
			};
		else {
			(function() {
				var _onload = window.onload;
				window.onload = function() {
					DOMReady.set();
					_onload();
				};
			})();
		}

		// Chargement de la librairie jQuery
		(function() {
			// on défini l'objet XmlHttpRequest qui nous permettra d'aller charger la librairie jQuery
			var xhr = (function() {
				if(typeof window.XMLHttpRequest != 'undefined')
					return new XMLHttpRequest();
				else if(typeof ActiveXObject != 'undefined') {
					try {
						return new ActiveXObject('Microsoft.XMLHTTP');
					} catch(e) {
						try {
							return new ActiveXObject('Msxml2.XMLHTTP');
						} catch(e2) {}
					}
				}
				throw(new Error('Impossible de faire des requêtes ajax'));
			})();

			// Lorsque la requete aura aboutie, on execute le code de jQuery, puis on lance execConfigFile
			xhr.onreadystatechange = function() {
				if(xhr.readyState == 4) {
					if(xhr.status != 200)
						throw(new Error('Librairie jQuery inaccessible'))
					eval(xhr.responseText);
					if(typeof jQuery != 'function')
						throw(new Error('Librairie jQuery invalide'))
					if(DOMReady())
						jQuery.ready();
					execConfigFile();
				}
			}

			// On execute la requete ajax
			try {
				xhr.open('GET', '/layoutftv/arches/common/javascripts/jquery.js', true);
				xhr.send(null);
			} catch(e) {
				throw(new Error('Impossible de charger la librairie jQuery : '+e.message));
			}
		})();
	}

	return {
		 loadConfig: function(config) {
			if(config.constructor != Array) {
				if((typeof config != 'object') || (typeof config.name != 'string'))
					throw(new Error('Le param&egrave;tre fourni n\'est pas dans un format valide'));
				config = [config];
			}
			execConfig(config);
		}
		,loadConfigFile: function(file) {
			if(typeof file != 'string')
				throw(new Error('Le param&egrave;tre fourni n\'est pas une chaine de caract&egrave;res'));
			execConfigFile(file);
		}
	};
})();