

/**
 * Fonctions utilisées par la pile de formulaires. On entend par pile, le système comportant plusieurs formulaires virtuellement placés en pile, et
 * dont un seul est affiché, la sélection s'effectuant par un système d'onglets.
 * L'utilisation de ce script nécessite tout d'abord la présence de la librairie de fonctions contenue dans le fichier de script tools.js.
 * Il est indispensable de disposer aussi pour la page du fichier CSS form.css
 * On active la gestion de la pile de formulaires par l'invocation de la fonction
 *   initForm()
 * que l'on peut placer dans l'attribut onload de la balise body de la page, et qui va gérer l'initialisation de la pile, mais aussi
 * des initialisations spécifiques de chaque type de formulaire (MEV, MEH, MEC, et MEP). Il est bien évident que pour cela on devra se référer aux
 * documentations de référence liées aux scripts formMEV.js, formMEH.js, formMEC.js, et formMEP.js, la présence de ces scripts dans la page dépendant
 * évidemement de la présence du formulaire associé. IL EST INUTILE D'INCLURE DANS UNE PAGE LES SCRIPTS ET CSS POUR UN FORMULAIRE QUI N'EST PAS UTILISE
 * DANS LA PILE DE CETTE PAGE
 *
 * Les onglets doivent être contenus dans une structure de liste comme suit:
 *   <!-- Le conteneur ul doit posséder la classe onglet -->
 *   <ul class="onglet">
 *     <!-- Chaque onglet doit avoir un id dont le nom commence par la chaine "onglet" -->
 *     <li id="ongletXXX">1er onglet</li>
 *     <li id="ongletYYY">2eme onglet</li>
 *     <!-- L'onglet disposant de la classe selected détermine quel formulaire est affiché par défaut -->
 *     <li id="ongletZZZ" class="selected">3eme onglet</li>
 *          ...
 *   </ul>
 *
 * Les formulaires sont alors définis par des tags block comme suit:
 *   <!-- Chaque formulaire doit avoir un id dont le nom commence par la chaine "form" -->
 *   <form id="formXXX"></form>
 *   <form id="formYYY"></form>
 *   <form id="formZZZ"></form>
 *     ...
 *
 * Il faut bien noter la correspondance entre les onglets et les formulaires ongletXXX <-> formXXX. La syntaxe utilisée ici à la place de XXX est libre.
 *
 *
 * Encapsulation de variables locales (privées).
 */
(function() {
	// Raccourci vers window
	var window = this,
			// Raccourci vers window.document
			document = window.document,
			// La fonction qui ne fait rien.
			NF = function() {},
			// Variables globales utilisées par toggle()
			fadeToElement, fadeFromElement,
			// Tableau permettant de stocker tous les objets formulaires (DOM) d'une même page.
			formsPile = [],
			// Raccourci vers ev.log
			LOG = window.ev && window.ev.log || {},
			// Raccourci vers ev.log.error()
			logError = LOG.error || (LOG.error = function(msg) { if (window.console) { window.console.error(msg); } }),
			// Raccourci vers ev.log.debug()
			logDebug = LOG.debug || (LOG.debug = function(msg) { if (window.console) { window.console.debug(msg); } }),
			// raccourcis vers les fonctions DOM
			evDomElement = window.ev && window.ev.dom && window.ev.dom.element || function(eltId) { return document.getElementById(eltId); };

	LOG.error('pileForms#<init>: DEPRECATED: utiliser le module ev.pileForms à la place.');

	// Pré-définition de méthodes (afin d'éviter que certaines soient absentes et génèrent des erreurs ; même si elles sont catchées)
	window.initFormMEV = NF;
	window.initFormMEH = NF;
	window.initFormMEC = NF;
	window.initFormMEP = NF;

	// Pré-définition de méthodes (afin d'éviter que certaines soient absentes et génèrent des erreurs ; même si elles sont catchées)
	window.readURLMEV = NF;
	window.readURLMEH = NF;
	window.readURLMEC = NF;
	window.readURLMEP = NF;

	/**
	 * Effectue l'analyse de l'URL d'appel de la page afin de pré-charger les champs input text
	 * correspondants dans une pile de formulaires.
	 */
	function readURL() {
		try {
			window.readURLMEV();
		}
		catch (e1) {
			logError(e1);
		}
		try {
			window.readURLMEH();
		}
		catch (e2) {
			logError(e2);
		}
		try {
			window.readURLMEC();
		}
		catch (e3) {
			logError(e3);
		}
		try {
			window.readURLMEP();
		}
		catch (e4) {
			logError(e4);
		}
	}

	/**
	 * Affiche un formulaire défini par son élément, en mettant à jour l'onglet associé avec la classe selected
	 * @param {Element} element Element DOM (Form) à montrer.
	 */
	window.showForm = function(element) {
		var onglet = evDomElement('onglet' + element.id.substring(4));
		if (onglet) {
			window.removeClass(onglet, 'unselected');
			window.addClass(onglet, 'selected');
		}
		if (!element.style || element.style.display != 'block') {
			element.style.display = 'block';
		}
	};

	/**
	 * Cache un formulaire défini par son élément, en mettant à jour l'onglet associé avec la classe unselected
	 * @param {Element} element Element DOM (Form) à cacher.
	 */
	window.hideForm = function(element) {
		var onglet = evDomElement('onglet' + element.id.substring(4));
		if (onglet) {
			window.addClass(onglet, 'unselected');
			window.removeClass(onglet, 'selected');
		}
		if (!element.style || element.style.display != 'none') {
			element.style.display = 'none';
		}
	};

	var createToggleAction;

	/**
	 * Fonction récursive servant à passer d'un formulaire à l'autre (fadeToElement à fadeFromElement) par un fade
	 * La récursion se fait en créant une action avec la fonction createToggleAction();
	 *
	 * @param {number=} time (optionnel) durée totale du processus de fade out & in, défaut 1000ms.
	 * @param {boolean=} fade (optionnel) si true fade out, si false fade in, default true.
	 */
	function toggle(time, fade) {
		// Si les paramètres ne sont pas définis, on définit les valeurs par défaut
		if (fade === undefined) {
			fade = true; // default fade out
		}
		if (!time) {
			time = 1000; // default 1s
		}
		var delay = 100, // interval 100ms
				delta = 2.0 * delay / time, // multiplié par deux car time est la durée du fade+appear
				opacity;
		// Si on est en phase de fade out
		if (fade) {
			// On récupère l'opacité de l'élément fadeFromElement et on la met à jour (-delta)
			opacity = parseFloat(fadeFromElement.style.opacity);
			opacity -= delta;
			// Si l'opacité est supérieure à delta (presque zéro)
			if (opacity > delta) {
				// On fixe la nouvelle valeur d'opacité, et on lance toggle récursivement
				window.setOpacity(fadeFromElement, opacity);
				window.setTimeout(createToggleAction(time, true), delay);
			}
			// Si l'opacité est inférieure à delta (presque zéro)
			else {
				// On fixe l'opacité à zéro, et on passe au fade in (récursivité par toggle())
				window.setOpacity(fadeFromElement, 0);
				window.hideForm(fadeFromElement);
				window.showForm(fadeToElement);
				window.setTimeout(createToggleAction(time, false), delay);
			}
		}
		// Si on est en phase de fade in
		else {
			// On récupère l'opacité de l'élément fadeToElement et on la met à jour (+delta)
			opacity = parseFloat(fadeToElement.style.opacity);
			opacity += delta;
			// Si l'opacité est presque à 1 (à delta près)
			if (opacity < (1 - delta)) {
				// On fixe la nouvelle valeur d'opacité, et on lance toggle récursivement
				window.setOpacity(fadeToElement, opacity);
				window.setTimeout(createToggleAction(time, false), delay);
			}
			// Si l'opacité est inférieure à 1 (à delta près)
			else {
				// On s'assure que l'élément fadeFromElement est invisible et fadeToElement est visible
				// avec les opacités idoines
				window.setOpacity(fadeToElement, 1);
				window.showForm(fadeToElement);
				window.setOpacity(fadeFromElement, 0);
				window.hideForm(fadeFromElement);
			}
		}
	}

	createToggleAction = function(time, fade) {
		return function() {
			toggle(time, fade);
		};
	};

	/**
	 * Fonction permettant de déterminer le formulaire initialement affiché, et initialisant la variable globale formsPile qui contient les éléments de type
	 * FORM constituant la pile.
	 * La sélection de ce formulaire s'effectue par la lecture des classes définies sur les onglets. Si l'onglet "ongletXXX"
	 * possède la classe "selected" son formulaire associé ("formXXX")est affiché par défaut
	 * initialise aussi les javascript onclick sur les onglets
	 **/
	window.initForm = function() {
		var forms = document.getElementsByTagName('FORM'), i, form, id, typ, onglet;
		if (!forms.length) {
			logError('Aucun formulaire (FORM) trouvé dans le document !');
			return;
		}
		for (i = 0; i < forms.length; i++) {
			form = forms[i];
			id = form.getAttribute('id'); // NB : il ne faut pas utiliser form.id (qui peut faire référence à un élément input du formulaire ayant un name="id")
			typ = typeof(id);
			if (typ === 'string') {
				onglet = evDomElement('onglet' + id.substring(4));
				if (onglet) {
					formsPile.push(form);
					window.addJavascriptToAttribute(onglet, 'onclick', "displayForm(ev.dom.element('" + id + "'));");
					if (window.hasClass(onglet, 'selected')) {
						window.showForm(form);
					}
					else {
						window.hideForm(form);
						window.addClass(onglet, 'unselected');
					}
				}
			}
		}
		try {
			window.initFormMEV();
		}
		catch (e1) {
			logError(e1);
		}
		try {
			window.initFormMEH();
		}
		catch (e2) {
			logError(e2);
		}
		try {
			window.initFormMEC();
		}
		catch (e3) {
			logError(e3);
		}
		try {
			window.initFormMEP();
		}
		catch (e4) {
			logError(e4);
		}

		// on lit l'url pour tester si elle contient des parametres existants (defini dans formMEV.js formMEH.js formMEC.js)
		// servant a preremplir les champs des formulaires. Si ils existent, la valeur de ces parametres va preremplir le formulaire.
		readURL();
	};

	var doFade = true; //par défaut le fadeout/fadein est activé
	/**
	 * Fait disparaitre le formulaire actuel en fade out, et apparaitre le nouveau formulaire dans un fade in
	 * @param {Element} element Element DOM (Form) à faire apparaitre.
	 **/
	window.displayForm = function(element) {
		// Si le formulaire à afficher est bien en display none on va lancer le toggle, sinon c'est inutile.
		if (element.style.display != 'block') {
			try {
				window.calendarPool.closeAll();
			}
			catch (e) {
				logError(e);
			}
			// L'identifiant passé détermine le fadeToElement (variable globale)
			fadeToElement = element;
			// On s'assure que l'élément fadeToElement est bien effacé et d'opacité zéro
			window.hideForm(fadeToElement);
			window.setOpacity(fadeToElement, 0);
			// On recherche l'élément actuellement affiché |-> fadeFromElement,
			// et on cache les autres éléments que fadeFromElement et fadeToElement et on les cache
			for (var i = 0; i < formsPile.length; i++) {
				var form = formsPile[i];
				if (form != element) {
					if (form.style.display == 'block') {
						fadeFromElement = form;
					}
					else {
						window.hideForm(form);
						window.setOpacity(form, 0);
					}
				}
			}
			// On s'assure que l'élément fadeFromElement est bien visible et d'opacité un
			if (fadeFromElement) {
				window.showForm(fadeFromElement);
				window.setOpacity(fadeFromElement, 1);
				if (doFade) { // On lance le toggle
					toggle(2000);// Le paramètre est optionnel
				}
				else { // On cache le formulaire actuel et on affiche le formulaire voulu
					window.hideForm(fadeFromElement);
					window.setOpacity(fadeFromElement, 0);
					window.showForm(fadeToElement);
					window.setOpacity(fadeToElement, 1);
				}
			}
			else {
				window.showForm(fadeToElement);
				window.setOpacity(fadeToElement, 1);
			}
		}
	};

	window.setTargetForm = function(targetForm) {
		try {
			window.setTargetFormMEV(targetForm);
		}
		catch (e1) {
			logError(e1);
		}
		try {
			window.setTargetFormMEH(targetForm);
		}
		catch (e2) {
			logError(e2);
		}
		try {
			window.setTargetFormMEC(targetForm);
		}
		catch (e3) {
			logError(e3);
		}
	};
}());

