

/**
 * Documentation principale sur DokuWiki : http://delhi/dokuwiki/doku.php?id=general:js:lang
 *
 * <b>Dans une page HTML, il faut les éléments obligatoires suivants :</b>
 * - la définition globale de la langue de la page (ex: <b>window.lang='fr_FR'</b> pour le français) ;
 * - l'appel à la librairie principale <b>http://cdn.easyvoyage.com/js/tools.js</b> ;
 * - les textes doivent être chargés <b>avant</b> les fichiers Javascript les utilisant.
 * (avec la méthode ev.lang.mapper.load(string...) ; cf. plus bas)
 *
 * <b>Les éléments de fonctionnement de l'outil :</b>
 * - Espace de noms ("package") : <b>ev.lang</b>
 * - Objet principal de ce module : <b>ev.lang.mapper</b>
 * (Objet unique, pas de classe correspondante, soit l'équivalent de l'instance d'un Singleton)
 * - Fichier à insérer dans la page : <b>http://cdn.easyvoyage.com/js/ev/lang/mapper.js</b>
 *
 * <b>Chargement des textes (exemple de chargement du namespace ev.lang.test.text) :</b>
 * &lt;script type="text/javascript"&gt;ev.lang.mapper.load('test.text');&lt;/script&gt;
 *
 * Beaucoup plus d'info sur DokuWiki.
 *
 *
 * _______________________________________________________
 * Fonction anonyme de déclaration de la classe gérant les
 * textes d'internationalisation.
 * Certaines fonctions ne sont visible que par les
 * classes concernées (déclarées ici).
 * Ce mécanisme de fonction anonyme permet de reproduire
 * un système d'encapsulation digne d'un langage de
 * programmation évolué (comme le Java).
 * Classes et éléments visibles seront stockés dans le
 * namespace 'ev.lang'.
 */
(function() {
	// raccourci vers window
	var window = this,
			// raccourci vers window.document
			document = window.document, wrt = 'writeln',
			// variable représentant undefined
			UNDEFINED,
			// raccourci vers window.ev
			ev = window.ev,
			// raccourci vers window.ev.tools
			TOOLS = ev && ev.tools,
			// raccourci vers window.ev.tools.array.indexOf
			arrayIndexOf = TOOLS && TOOLS.array.indexOf,
			// raccourci vers window.ev.jsd (JS Directory)
			JSD = ev && ev.jsd,
			// raccourci vers window.ev.log
			LOG = ev && ev.log,
			// raccourci vers window.ev.lang
			LANG,
			// raccourci vers window.ev.path
			PATH,
			// expression reg. représentant un point
			DOT_PAT = /\./,
			// nom du module courant
			MOD_NAME = 'lang.mapper',
			// tableau qui contiendra les modules de langue déjà chargés
			loaded = [];

	if (!ev) {throw MOD_NAME + '#<init>: Needs module ev.core !';}


	LANG = ev.lang;
	PATH = ev.path;

	/**
	 * Méthode permettant de déclencher le téléchargement des fichiers
	 * correspondant aux groupes de traductions donnés en paramètres.<br>
	 * (Les groupes sont donnés sous forme de namespaces)<br>
	 *<br>
	 * ex: mapper.load("test.text", "test.img", ...);<br>
	 *<br>
	 * <b>NB:</b> Il est aussi possible d'utiliser le Tag 'js:include'
	 * avec l'attribut 'tradGroup' pour charger les groupes de
	 * traductions.<br>
	 * (ex: &lt;js:include tradGroup="mev.results" /&gt;)
	 *
	 * @param {!Arguments} args tableau de paramètres (autant de
	 *   paramètres que de namespaces à charger).
	 */
	function loadTradGroup(args) {
		var len = args.length, file,
				scripts = [];
		while (len) {
			--len;
			file = args[len].replace(DOT_PAT, '/');
			if (!loaded.length || arrayIndexOf(loaded, file) < 0) {
				loaded.push(file);
				LOG.debug(MOD_NAME + '#load(): Treating file \'' + file + '[_' + LANG.current + '].js\'...');
				scripts.push('<script type="text/javascript" charset="iso-8859-1" src="' + PATH.js + '/ev/lang/' + file + '_' + LANG.current + '.js"></script>');
				LOG.debug(MOD_NAME + '#load(): Added script ' + scripts[scripts.length - 1]);
				scripts.push('<script type="text/javascript" charset="iso-8859-1" src="' + PATH.js + '/ev/lang/' + file + '.js"></script>');
				LOG.debug(MOD_NAME + '#load(): Added script ' + scripts[scripts.length - 1]);
			}
			else {
				LOG.error(MOD_NAME + "#load(): Mapping de langue déjà chargé pour '" + file + "'.");
			}
		}

		// Ajout des scripts dans le DOM (ils vont être exécutés à la volée)
		len = scripts.length;
		while (len) {
			--len;
			// FIXME trouver un moyen d'utiliser ev.djs (Attention, ça ne sera plus synchrone mais asynchrone)
			document[wrt](scripts[len]);
		}
	}

	/**
	 * Méthode permettant de déclencher le téléchargement des fichiers
	 * correspondant aux groupes de traductions donnés en paramètres et
	 * d'exécuter une action en fin de téléchargement via un callback.<br>
	 * (Les groupes sont donnés sous forme de namespaces)<br>
	 *<br>
	 * ex: mapper.load("test.text", "test.img", ...);<br>
	 *<br>
	 * <b>NB:</b> Il est aussi possible d'utiliser le Tag 'js:include'
	 * avec l'attribut 'tradGroup' pour charger les groupes de
	 * traductions.<br>
	 * (ex: &lt;js:include tradGroup="mev.results" /&gt;)
	 *
	 * @param {!Arguments} args tableau de paramètres (autant de
	 *   paramètres que de namespaces à charger + le callback si
	 *   besoin).
	 */
	function requireTradGroup(args) {
		var len = args.length, file,
				scripts = [],
				onReady;
		if (len) {
			LOG.debug(MOD_NAME + '#requireTradGroup(): ' + len + ' arguments.');

			if (len > 1) {
				if (typeof(onReady = args[len - 1]) === 'function') {
					--len;
				}
				else {
					onReady = 0;
				}
			}
			LOG.debug(MOD_NAME + '#requireTradGroup(): len=' + len + ' ; onReady=' + onReady);

			while (len) {
				--len;
				file = args[len].replace(DOT_PAT, '/');
				LOG.debug(MOD_NAME + '#requireTradGroup(): len=' + len + ' ; onReady=' + onReady + ' file=' + file);
				LOG.debug(MOD_NAME + '#requireTradGroup(): Importing traduction group \'' + file + '[_' + LANG.current + ']\' (with ev.jsd module)...');
				scripts.push('ev.lang.' + file);
				LOG.debug(MOD_NAME + '#requireTradGroup(): Added module ' + scripts[scripts.length - 1]);
				scripts.push('ev.lang.' + file + '_' + LANG.current);
				LOG.debug(MOD_NAME + '#requireTradGroup(): Added module ' + scripts[scripts.length - 1]);
			}

			// Chargement dynamique des scripts (ils vont être exécutés en asynchrone)
			if (onReady) {
				scripts.push(onReady);
			}
			JSD.require.apply(JSD, scripts);
		}
	}

	/**
	 * Objet principal gérant le chargement des propriétés textes.
	 */
	LANG.mapper = {
		/**
		 * Action déléguée à la fonction #loadTradGroup(Array).
		 *
		 * param {...string} tradGroups un ou plusieurs noms de groupes de traductions à charger.
		 * @deprecated utiliser #require(...string, Function).
		 */
		load: function() {
			loadTradGroup(arguments);
		},

		/**
		 * Action déléguée à la fonction #requireTradGroup(Array, onReady).
		 *
		 * param {string} tradGroups un ou plusieurs noms de groupes de traductions à charger
		 *   (les séparer par des virgules pour en charger plusieurs).
		 * param {Function=} onReady fonction de callback à exécuter dés que tout est téléchargé (optionnel).
		 */
		require: function() {
			requireTradGroup(arguments);
		},

		/**
		 * Permet le chargement des propriétés textes à l'intérieur
		 * des différents fichiers chargés via load().
		 *
		 * Doit se trouver au moins une fois par fichier chargé avec load().
		 *
		 * ex: mapper.set("test.text", {var1: "bonjour", var2: "au revoir"});
		 *
		 * @param {String} chemin chemin du fichier de propriétés de langues.
		 * @param {Object} vars tableaux associatif (JSON) des variables à ajouter.
		 */
		set: function(chemin, vars) {
			var len, tmpPath = LANG, path = chemin.split(DOT_PAT), n = 0;
			LOG.debug(MOD_NAME + '#set(): chemin=' + chemin + ' ; tmpPath=' + tmpPath + ' ; path=[' + path + '] ; n=' + n);
			LOG.debug(MOD_NAME + '#set(): Parcours du chemin des variables...');
			while (n < path.length) {
				if (path[n].length) {
					LOG.debug(MOD_NAME + '#set(): Entering into \'' + path[n] + '\'...');
					if (!tmpPath[path[n]]) {
						// si l'espace de noms n'existe pas, on le crée
						LOG.debug(MOD_NAME + '#set(): Creating new namespace \'' + path[n] + '\'...');
						tmpPath[path[n]] = {};
					}
					LOG.debug(MOD_NAME + '#set(): -> \'' + path[n] + '\'');
					tmpPath = tmpPath[path[n]];
				}
				else {
					LOG.error(MOD_NAME + '#set(): Espace de noms contenant des vides \'' + chemin + '\'');
				}
				++n;
			}

			// Itération sur les variables à insérer
			LOG.debug(MOD_NAME + '#set(): Insertion/remplacement des variables...');
			TOOLS.extend(tmpPath, vars, 1);
		},

		/**
		 * Retourne la propriété donnée si définie et '' sinon.
		 * @param {String} p propriété à tester et afficher.
		 * @param {String} n nom de la propriété (facultatif).
		 */
		ifdef: function(p, n) {
			if (p !== UNDEFINED) {
				return p;
			}
			else {
				LOG.debug(MOD_NAME + '#ifdef(): Propriété non définie ' + (n ? n + '=' : '') + p);
				return '&nbsp;';
			}
		}
	};

	LOG.debug(MOD_NAME + '#<init>: OK');
}()); // exécution de la fonction anonyme, ici

