

/**
 * Fonctions utilisées par le formulaire MEH, ce script est invoqué par form.js
 * L'utilisation des calendriers impose aussi l'utilisation de calendar.js et calendar.css
 * L'utilisation de la completion impose l'utilisation de completionMEH.js et completionMEH.css
 *
 * Encapsulation de variables locales (privées).
 */
(function() {
	// Raccourci vers window
	var WIN = this,
			// Raccourci vers document
			DOC = WIN.document,
			// Raccourci vers window.ev
			EASY = WIN.ev,
			// Raccourci vers window.ev.log
			LOG = EASY && EASY.log, warnMsg = LOG && LOG.warn,
			// Raccourci vers window.ev.dom
			DOM = EASY && EASY.dom,
			// Raccourci vers window.ev.forms.util
			FORMS = EASY && EASY.forms && EASY.forms.util,
			// Raccourci vers fonctions utiles
			getElementById = DOM && DOM.element,
			addClass = DOM && DOM.addClass,
			removeClass = DOM && DOM.removeClass,
			setFieldStyleError = FORMS && FORMS.setFieldError,
			resetFieldStyleError = FORMS && FORMS.resetFieldError,
			capTextField = FORMS && FORMS.capTextField,
			isValidDate = WIN.isValidDate,
			createDate = WIN.createDate,
			initJours = WIN.initJours,
			initMois = WIN.initMois,
			addJavascriptToAttribute = WIN.addJavascriptToAttribute,
			autoFillLieuFromUrl = EASY && EASY.forms && EASY.forms.autoFillLieuFromUrl,
			genericNavigator = WIN.genericNavigator,
			MSIE = WIN.MSIE,
			submitValueSubmitME = WIN.submitValueSubmitME,
			waitValueSubmitME = WIN.waitValueSubmitME,
			// Indique si le formulaire MEH a déjà été setté
			flagInitFormMEH = false,
			allerMEH,
			retourMEH,
			// Indique si le formulaire est erroné
			errorMEH,
			errorDestinationsMEH,
			errorDatesMEH,
			JOUR = 24 * 60 * 60 * 1000;

	if (!EASY || !DOM) { throw 'Needs ev.core and ev.dom modules!'; }

	/**
	 * Désactive les options du sélecteur en fonction d'une date de référence.
	 * @param {!{d: !Element, m: !Element}} mySelect groupe de Sélecteurs choisi ("allerMEH" ou "retourMEH").
	 * @param {!Date} myDate Date du selecteur.
	 * @param {!Date} refDate Date minimum.
	 * @param {boolean=} forceClean Optionel, oblige le repositionnement des sélecteurs, utile à l'INIT et pour IE.
	 * @private
	 */
	function limitDateChoices(mySelect,myDate,refDate,forceClean) {
		var now = new Date();
		refDate = refDate || now;
		forceClean = forceClean || false;
		var refY = refDate.getFullYear(), refM = refDate.getMonth(), daysForm, monthsForm;
		if (mySelect === allerMEH || mySelect === retourMEH) {
			daysForm = mySelect.d;
			monthsForm = mySelect.m;
		} else { return; }
		//if(mySelect===allerMEH){LOG.info(">limitDateChoicesMEH ALLER");}
		//if(mySelect===retourMEH){LOG.info(">limitDateChoicesMEH RETOUR");}
		//LOG.info(">>limitDateChoicesMEH "+myDate.getDate()+" "+myDate.getMonth());
		var cleanSel = false, // supprime les paramètres "disabled", si aucun élément de la liste ne doit être bloqué.
				currentTestedSelectMonth = 0,
				currentTestedSelectYear = 0,
				currentTestedSelectDay = 0,
				currentSelectedOptionMonth,
				currentSelectedOptionDay,
				i, k;
		if (myDate.getMonth() < 9) {
			currentSelectedOptionMonth = '0' + (myDate.getMonth() + 1) + '/' + myDate.getFullYear();
		} else {
			currentSelectedOptionMonth = (myDate.getMonth() + 1) + '/' + myDate.getFullYear();
		}
		if (myDate.getDate() < 10) {
			currentSelectedOptionDay = '0' + myDate.getDate();
		} else {
			currentSelectedOptionDay = myDate.getDate() + '';
		}
		// LOG.info(">>>limitDateChoicesMEH "+currentSelectedOptionDay+"
		// "+currentSelectedOptionMonth+" ");
		for (i = 0; i < monthsForm.options.length; i++) {
			monthsForm.options[i].disabled = false;
			removeClass(monthsForm.options[i], 'disabled');
			if (forceClean && monthsForm.options[i].value === currentSelectedOptionMonth) {
				monthsForm.selectedIndex = i;
				//LOG.info(">>>>limitDateChoicesMEH MONTH ok!"+i);
			}
			currentTestedSelectMonth = parseInt(monthsForm.options[i].value.replace(/\/[0-9]{4}$/, ''), 10) - 1;
			currentTestedSelectYear = parseInt(monthsForm.options[i].value.replace(/^[0-9]{2}\//, ''), 10);
			if (currentTestedSelectYear < refY || currentTestedSelectYear === refY && currentTestedSelectMonth < refM) {
				// CURRENT IT YEAR < REF YEAR || CURRENT IT YEAR = REF YEAR & CURRENT IT MONTH < REF MONTH : on cache le mois inaccessible
				monthsForm.options[i].disabled = true;
				addClass(monthsForm.options[i], 'disabled');
				cleanSel = false;
			}
			else if (currentTestedSelectYear === refY && myDate.getFullYear() === refY)// CURRENTYEARSelect = REFYEAR, and ,MYYEAR = REFYEAR
			{
				if (currentTestedSelectMonth === myDate.getMonth() && currentTestedSelectMonth === refM)// CURRENTMONTHSelect == MYMONTH, and ,CURRENTMONTHSelect == REFMONTH
				{
					for (k = 0; k < daysForm.options.length; k++)
					{
						daysForm.options[k].disabled = false;
						removeClass(daysForm.options[k], 'disabled');
						currentTestedSelectDay = parseInt(daysForm.options[k].value, 10);
						if (forceClean && daysForm.options[k].value === currentSelectedOptionDay) {
							daysForm.selectedIndex = k;
							//LOG.info(">>>>>limitDateChoicesMEH DAY ok!"+i);
						}
						if (currentTestedSelectDay === now.getDate() && currentTestedSelectDay <= refDate.getDate() || currentTestedSelectDay <= refDate.getDate())// J-0 si RefDate==now, sinon J-1 meme.
						{
							daysForm.options[k].disabled = true;
							addClass(daysForm.options[k], 'disabled');
						}
						cleanSel = true;
					}
				}
			}
		}
		if (!cleanSel)
		{
			for (i = 0; i < daysForm.options.length; i++)
			{
				if (forceClean && daysForm.options[i].value === currentSelectedOptionDay) {
					daysForm.selectedIndex = i;
					//LOG.info(">>>>>limitDateChoicesMEH DAY ok!"+i);
				}
				daysForm.options[i].disabled = false;
				removeClass(daysForm.options[i], 'disabled');
			}
		}
	}
	/**
	 * Initialise les dates par défaut en utilisant l'horloge du client, la règle est la suivante pour la date aller: c'est le
	 * prochain vendredi jusqu'au mercredi, et le vendredi en 8 à partir du jeudi. La date retour est le vendredi suivant
	 * la date aller.
	 * On faire abstraction des dates par défaut précédentes et fixer les dates aller et retour en les passant en paramètre
	 * au format jj/mm/aaaa
	 *
	 * @param {string=} dateDepartText date aller sous forme de texte (optionnelle ; par défaut new Date()).
	 * @param {string=} dateReturnText date retour (optionnelle).
	 **/
	function initDates(dateDepartText,dateReturnText) {
		//LOG.info("FORM MEH initDates Aller:"+dateDepartText+", Return:"+dateReturnText);
		var jourMEHAller,
				moisMEHAller,
				jourMEHRetour,
				moisMEHRetour,
				jourAller,
				moisAller,
				anneeAller,
				jourRetour,
				moisRetour,
				anneeRetour,
				dateAller,
				dateRetour;
		if (getElementById('jourDebutMEH')) {jourMEHAller = getElementById('jourDebutMEH');}
		if (getElementById('moisDebutMEH')) {moisMEHAller = getElementById('moisDebutMEH');}
		if (getElementById('jourFinMEH')) {jourMEHRetour = getElementById('jourFinMEH');}
		if (getElementById('moisFinMEH')) {moisMEHRetour = getElementById('moisFinMEH');}
		if (!(jourMEHAller && moisMEHAller && jourMEHRetour && moisMEHRetour)) {return;}

		/*Gestion du delta*/
		var now = new Date(),
				day = now.getDay(),
				delta = 5 - day;
		if (delta <= 1) {delta += 1;}

		/* -------------------------------- */
		/* ALLER */
		if (dateDepartText && dateDepartText.match(/[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/)) {
			jourAller = dateDepartText.replace(/\/[0-9]{1,2}\/[0-9]{4}$/, '');
			moisAller = dateDepartText.replace(/^[0-9]{1,2}\/|\/[0-9]{4}$/g, '');
			anneeAller = dateDepartText.replace(/[0-9]{1,2}\//g, '');
			dateAller = new Date(parseInt(anneeAller, 10), parseInt(moisAller, 10) - 1, parseInt(jourAller, 10));
		}
		else {
			dateAller = new Date();
			dateAller.setTime(now.getTime() + delta * JOUR);
			jourAller = '' + dateAller.getDate();
			if (dateAller.getDate() < 10) {jourAller = '0' + dateAller.getDate();}
			moisAller = '' + (dateAller.getMonth() + 1);
			if (dateAller.getMonth() < 9) {moisAller = '0' + (dateAller.getMonth() + 1);}
			moisAller += '/' + dateAller.getFullYear();
		}
		jourMEHAller.value = jourAller;
		moisMEHAller.value = moisAller;
		allerMEH = {d: jourMEHAller, m: moisMEHAller};
		limitDateChoices(allerMEH, dateAller, now, true);

		/* -------------------------------- */
		/* DERNIER JOUR POSSIBLE DU FORMULAIRE */

		var lastDayOfFormMEH = jourMEHRetour.options[jourMEHRetour.options.length - 1].value,
				lastMonthOfFormMEH = moisMEHRetour.options[moisMEHRetour.options.length - 1].value,
				lMValue = lastMonthOfFormMEH.replace(/\/[0-9]{4}$/g, ''),
				lYValue = lastMonthOfFormMEH.replace(/^[0-9]{1,2}\//g, ''),
				lD = parseInt((lastDayOfFormMEH), 10),
				lM = parseInt((lMValue - 1), 10),
				lY = parseInt(lYValue, 10),
				lastDateOfFormMEH = new Date(lY, lM, lD);

		/* -------------------------------- */
		/* RETOUR */
		if (dateReturnText && dateReturnText.match(/[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/)) {
			jourRetour = dateReturnText.replace(/\/[0-9]{1,2}\/[0-9]{4}$/, '');
			moisRetour = dateReturnText.replace(/^[0-9]{1,2}\/|\/[0-9]{4}$/g, '');
			anneeRetour = dateReturnText.replace(/[0-9]{1,2}\//g, '');
			dateRetour = new Date(parseInt(anneeRetour, 10), parseInt(moisRetour, 10) - 1, parseInt(jourRetour, 10));
		}
		else {
			dateRetour = new Date();
			dateRetour.setTime(dateAller.getTime() + 1 * JOUR);
			while ((lastDateOfFormMEH - dateRetour) < 0) {dateRetour.setTime(dateRetour.getTime() - JOUR);}// Si RETOUR > LASTDATE, on revient en arrière, jusqu'à la date ALLER, s'il le faut.
			jourRetour = '' + dateRetour.getDate();
			if (dateRetour.getDate() < 10) {jourRetour = '0' + dateRetour.getDate();}
			moisRetour = '' + (dateRetour.getMonth() + 1);
			if (dateRetour.getMonth() < 9) {moisRetour = '0' + moisRetour;}
			moisRetour += '/' + dateRetour.getFullYear();
		}
		/* Si la date de retour proposée est supérieur au dernier jour du formulaire, date RETOUR = date ALLER */
		jourMEHRetour.value = jourRetour;
		moisMEHRetour.value = moisRetour;
		retourMEH = {d: jourMEHRetour, m: moisMEHRetour};
		limitDateChoices(retourMEH, dateRetour, dateAller, true);
	}
	// Fonctions de compatibilité ancien moteurs (v2)
	WIN.initMEHDates = initDates;

	/**
	 * FIXME Identique à celle de MEV et MEC (à factoriser)
	 * errorDisplay : Affiche la première erreur qui a été détectée.
	 * @param {Array} el : Tableaux des différents ID du champ d'erreur.
	 * @private
	 */
	function errorDisplay(el,errList) {
		//console.info("errorDisplay BEGIN");
		var elt, i, cnt = errList.length;
		for (i = 0; i < cnt; ++i) {
			elt = getElementById(errList[i]);
			if (elt) {
				elt.style.display = 'none';
			}
		}
		elt = getElementById(el && el[0]);
		if (elt) {
			elt.style.display = 'block';
		}
		//console.info("errorDisplay END");
	}

	/**
	 * verifyDatesFormMEH : test la validité des champs de dates.
	 * @param {boolean=} isEvent : Définit si l'appel est direct ou provient d'un evenement.
	 * @return {!boolean} "true" si le formulaire est valide.
	 */
	WIN.verifyDatesFormMEH = function(isEvent) {
		/* Permet de déterminer l'élément et la nature de l'évènement */
		var eventTarget = false, currentTarget;
		if (isEvent !== undefined &&
				typeof isEvent !== 'string' &&
				typeof isEvent !== 'boolean') {
			if (!isEvent) {isEvent = WIN.event;}
			if (isEvent.target) {currentTarget = isEvent.target;}
			else if (isEvent.srcElement) {currentTarget = isEvent.srcElement;}
			if (currentTarget && currentTarget.nodeType === 3) {currentTarget = currentTarget.parentNode;}// // Redéfinition de la cible si c'est un noeud texte (cf bug Safari)
			if (currentTarget) {eventTarget = currentTarget.id;}
		}
		else {eventTarget = isEvent || false;}

		//LOG.info("FORM MEH verifyDatesFormMEH()");
		var ADateObj = {d: 'jourDebutMEH', m: 'moisDebutMEH', err: 'errorMEHDateDebutErronee'},
				RDateObj = {d: 'jourFinMEH', m: 'moisFinMEH', err: 'errorMEHDateFinErronee'},
				reversedDateList = {radio: 'typeMEHAR', err: 'errorMEHDatesInversees'},
				errorsList = [ADateObj.err, RDateObj.err, reversedDateList.err],
				errorsToDisplay = [], isReverted = false, aller, retour;
		// Remise à false
		errorDatesMEH = false;
		/**
		 * isValid : test si la date est correctement formatée et si elle est passée.
		 * @param {!string} _d ID selecteur.
		 * @param {!string} _m ID selecteur.
		 * @param {!string} errorEl ID selecteur.
		 * @return {{date: !Date, d: !(number|string), m: !(number|string), y: !number, valid: !boolean}}
		 */
		function isValid(_d,_m,errorEl) {
			var day = parseInt(getElementById(_d).value, 10),
					month = parseInt(getElementById(_m).value.replace(/\/[0-9]{4}$/, ''), 10),
					year = parseInt(getElementById(_m).value.replace(/^[0-9]{2}\//, ''), 10);
			//LOG.info("FORMMEH "+day+"/"+month+"/"+year+" est valide?"+isValidDate(day,month,year));
			if (!isValidDate(day, month, year)) {
				if (!errorDatesMEH) {errorDatesMEH = true;}
				errorsToDisplay.push(errorEl);
				if (day < 10) {day = '0' + day;}
				if (month < 10) {month = '0' + month;}
				return {
					date: createDate(day, month, year),
					d: day,
					m: month,
					y: year,
					valid: false
				};
			}
			if (day < 10) {day = '0' + day;}
			if (month < 10) {month = '0' + month;}
			return {
				date: createDate(day, month, year),
				d: day,
				m: month,
				y: year,
				valid: true
			};
		}
		/**
		 * isDatesReversed : compare les 2 dates : affiche une erreur que pour l'Aller.
		 * @param {!{date: !Date, d: (number|string), m: (number|string), y: number, valid: boolean}} first premier objet date à comparer
		 * @param {!{date: !Date, d: (number|string), m: (number|string), y: number, valid: boolean}} second deuxième objet date à comparer
		 * @param {!string} errorEl : ID selecteur.
		 * @return {boolean} true si les dates sont inversées.
		 */
		function isDatesReversed(first, second, errorEl) {
			//      var myparentId;
			if (first.date.getTime() > second.date.getTime()) {
				//        if(isEvent&&typeof(isEvent)!=='boolean'){
				//          myparentId=isEvent.target.parentNode.getAttribute('id');
				//        }
				var now = new Date();
				//LOG.warn("FORMMEH Les Dates sont inversées");
				if (first.y > now.getFullYear() && first.m === 12 && first.d > 24)// FIXME [acollin] conditions en DUR, doivent être paramétrées en fonction de la dernière date proposée dans le selecteur de date.
				// devrait ressembler à : first.m===lastMonth && first.d===(lastDay - delta)
				{
					//LOG.warn("On est en fin d'année alors on affiche l'erreur");
					errorsToDisplay.push(errorEl);
				}
				errorsToDisplay.push(errorEl);
				if (!errorDatesMEH) {errorDatesMEH = true;}
				return true;
			}
			return false;
		}
		//INIT
		var now;
		errorDisplay(errorsToDisplay, errorsList);
		aller = isValid(ADateObj.d, ADateObj.m, ADateObj.err);
		retour = isValid(RDateObj.d, RDateObj.m, RDateObj.err);
		if (!errorDatesMEH) {errorDatesMEH = (isReverted = isDatesReversed(aller, retour, reversedDateList.err));}
		//LOG.info("isErrorMEH "+errorMEH);
		if (eventTarget === ADateObj.d || eventTarget === ADateObj.m) {
			if (aller.valid && retour.valid && !isReverted && !errorDatesMEH) {
				//console.log("MEH OK");
				initDates(aller.d + '/' + aller.m + '/' + aller.y, retour.d + '/' + retour.m + '/' + retour.y);
				errorDatesMEH = false;
			}
			else if (!aller.valid) {
				//console.log("MEH !aller.valid");
				now = new Date();
				limitDateChoices(allerMEH, aller.date, now.date);
			}
			else if (!retour.valid || isReverted) {
				//console.log("MEH !retour.valid||isReverted");
				initDates(aller.d + '/' + aller.m + '/' + aller.y);
				errorDatesMEH = false;
			}
		}
		else if (eventTarget === RDateObj.d || eventTarget === RDateObj.m) {
			if (aller.valid && retour.valid && !isReverted && !errorDatesMEH) {
				initDates(aller.d + '/' + aller.m + '/' + aller.y, retour.d + '/' + retour.m + '/' + retour.y);
				errorDatesMEH = false;
			}
			else if (!retour.valid || isReverted) {
				limitDateChoices(retourMEH, retour.date, aller.date);
			}
		}
		else {
			if (aller.valid && retour.valid && !isReverted && !errorDatesMEH) {
				initDates(aller.d + '/' + aller.m + '/' + aller.y, retour.d + '/' + retour.m + '/' + retour.y);
				errorDatesMEH = false;
			}
			else if (!aller.valid) {
				now = new Date();
				limitDateChoices(allerMEH, aller.date, now.date);
			}
			else if (!retour.valid || isReverted) {
				limitDateChoices(retourMEH, retour.date, aller.date);
			}
		}
		if (isEvent && errorDatesMEH || errorsToDisplay && errorDatesMEH) {
			errorDisplay(errorsToDisplay, errorsList);
		}
		LOG.info('formMEH#verifyDatesFormMEH(' + isEvent + '): end [error=' + errorDatesMEH + ']');
		return errorDatesMEH;
	};
	/**
	 * verifyDestinationFormMEH : test la validité des champs de destination et de voyageurs.
	 * @param {boolean=} isEvent : Définit si l'appel est direct ou provient d'un evenement.
	 * @return {!boolean} "true" si le formulaire est valide.
	 */
	WIN.verifyDestinationsFormMEH = function(isEvent) {
		//LOG.info("FORM MEH verifyDestinationsFormMEH()");
		var CurrentDestObj = 'lieuMEH',
				testDestList = {el: CurrentDestObj, err: 'errorMEHLieuVide'},
				unknowedDestList = {el: CurrentDestObj, err: 'lieuMEHPropError'},
				errorsList = [testDestList.err, unknowedDestList.err],
				curError,
				curInput,
				errorsToDisplay = [];
		// Remise à false
		errorDestinationsMEH = false;
		/**
		 * isEmpty : renvoie "false" si le paramètre existe et qu'il a une valeur, sinon "true".
		 * @param {!string} el ID selecteur.
		 * @return {boolean} <code>true</code> si l'élément donné est vide, sinon <code>false</code>.
		 */
		function isEmpty(el) {
			el = getElementById(el);
			if (el && !el.value) {
				setFieldStyleError(el);
				errorsToDisplay.push(testDestList.err);
				//el.focus();
				return (errorMEH = true);
			}
			return false;
		}
		//INIT
		errorDisplay(errorsToDisplay, errorsList);
		//TEST
		if (getElementById(testDestList.err)) {
			curError = getElementById(testDestList.err);
			curError.style.display = 'none';
		}
		if (getElementById(CurrentDestObj)) {
			curInput = getElementById(CurrentDestObj);
			resetFieldStyleError(curInput);
			capTextField(curInput, 30);
		}
		if (isEvent) {
			if (EASY.me && EASY.me.PropositionManager) {
				if (!errorDestinationsMEH) {errorDestinationsMEH = isEmpty('lieuIataMEH');}
				if (errorDestinationsMEH) {
					EASY.dom.element('submitMEH').focus();
				}
			}else {
				if (!errorDestinationsMEH) {errorDestinationsMEH = isEmpty('CurrentDestObj');}
			}
		}
		if (isEvent || errorsToDisplay) {errorDisplay(errorsToDisplay, testDestList.err);}
		return errorDestinationsMEH;
	};

	/**
	 * Cette fonction vérifie la cohérence des données du formulaire MEH et active éventuellement les messages d'erreur.
	 * Cette fonction retourne aussi un booléen qui indique si le formulaire est sans erreur, donc retourne true si aucune
	 * erreur n'est présente, false dans le cas contraire
	 **/
	WIN.verifyFormMEH = function(isEvent) {
		// INIT
		var affErrorMEHDate = false;//l'affichage des erreurs de date sur les formaulaires MEH n'est intégré que sur les sites principaux et pas encore sur les affiliés
		if ((WIN.location.href).match(/seoul/) || (WIN.location.href).match(/tokyo/) || (WIN.location.href).match(/test/) || (WIN.location.href).match(/easyviajar.com/) || (WIN.location.href).match(/easyviaggio.com/) || (WIN.location.href).match(/easyvoyage.co.uk/) || (WIN.location.href).match(/easyvoyage.de/) || (WIN.location.href).match(/easyvoyage.com/) || (WIN.location.href).match(/avion.fr/))
		{affErrorMEHDate = true;}
		errorMEH = false;
		errorDatesMEH = WIN.verifyDatesFormMEH(isEvent);
		errorDestinationsMEH = WIN.verifyDestinationsFormMEH(isEvent);
		if (errorDestinationsMEH || errorDatesMEH) {errorMEH = true;}
		return !errorMEH;
	};
	/**
	 * Fonction invoquée par initForm() du script form.js
	 **/
	WIN.initFormMEH = function() {
		if (!flagInitFormMEH) {flagInitFormMEH = true;}
		else {return;}
		var formMEH = getElementById('formMEH');
		if (!formMEH) {
			LOG.error("initFormMEH> Can't find 'formMEH' element!");
			return;
		}
		if (genericNavigator.navigator.id == MSIE) {
			addJavascriptToAttribute(formMEH, 'onsubmit', 'cancelIEEvent();submitFormMEH();');
		}
		else {
			addJavascriptToAttribute(formMEH, 'onsubmit', 'submitFormMEH();return false;');
		}

		// Ajout des calendriers dynamiques (si les icones sont présentes)
		var lieuMEH = getElementById('lieuMEH'),
				errorMEHLieuVide = getElementById('errorMEHLieuVide'),
				jourDebutMEH = getElementById('jourDebutMEH'),
				moisDebutMEH = getElementById('moisDebutMEH'),
				jourFinMEH = getElementById('jourFinMEH'),
				moisFinMEH = getElementById('moisFinMEH'),
				calendrierMEHDebutIcon = getElementById('calendrierMEHDebutIcon'),
				calendrierMEHFinIcon = getElementById('calendrierMEHFinIcon'),
				calendrierMEHDebut = getElementById('calendrierMEHDebut'),
				calendrierMEHFin = getElementById('calendrierMEHFin'),
				calendarMEHdebut, calendarMEHFin;

		initJours(jourDebutMEH);
		initMois(moisDebutMEH);
		initJours(jourFinMEH);
		initMois(moisFinMEH);
		var lieuClickListener = function(e) {
			if (!e) {e = WIN.event;}
			if (e && errorMEHLieuVide && errorMEHLieuVide.style.display === 'block') {errorMEHLieuVide.style.display = 'none'; }
		};
		var formChangeListener = function(e) {
			if (!e) {e = WIN.event;}
			WIN.verifyDatesFormMEH(e);
		};
		var formClickListener = function() {
			calendarMEHdebut.hide('cache ALLER');
			calendarMEHFin.hide('cache RETOUR');
		};
		if (jourDebutMEH && moisDebutMEH && calendrierMEHDebutIcon && calendrierMEHDebut) {
			try {
				calendarMEHdebut = new WIN.Calendar(jourDebutMEH, moisDebutMEH, calendrierMEHDebut, formChangeListener);
				calendrierMEHDebutIcon.onclick = function() {
					calendarMEHdebut.clicAction(calendarMEHdebut.poolIndex, true);
				};
			}
			catch (e1) {
				LOG.error('initFormMEH> problème de définition du calendrier début MEH : ' + e1);
			}
		}
		if (jourFinMEH && moisFinMEH && calendrierMEHFinIcon && calendrierMEHFin) {
			try {
				calendarMEHFin = new WIN.Calendar(jourFinMEH, moisFinMEH, calendrierMEHFin, formChangeListener);
				calendrierMEHFinIcon.onclick = function() {
					calendarMEHFin.clicAction(calendarMEHFin.poolIndex, true);
				};
			}
			catch (e2) {
				LOG.error('initFormMEH> problème de définition du calendrier fin MEH : ' + e2);
			}
		}
		if (lieuMEH) {lieuMEH.onclick = lieuClickListener; }
		jourDebutMEH.onchange = formChangeListener;
		moisDebutMEH.onchange = formChangeListener;
		jourFinMEH.onchange = formChangeListener;
		moisFinMEH.onchange = formChangeListener;
		jourDebutMEH.onclick = formClickListener;
		moisDebutMEH.onclick = formClickListener;
		jourFinMEH.onclick = formClickListener;
		moisFinMEH.onclick = formClickListener;
		// Ajout des des auto completions (si les élémentes de positionnement sont présents, ainsi que les champs hidden data)
		var lieuDataMEH = getElementById('lieuDataMEH') || getElementById('lieuIataMEH');
		var propositionsMEH = getElementById('propositionsMEH');
		var nombrePropositionsCompletionMEH = 12;
		if (lieuMEH && lieuDataMEH && propositionsMEH) {
			try {
				var compl = new WIN.CompletionMEH(lieuMEH, lieuDataMEH, propositionsMEH, nombrePropositionsCompletionMEH);
				if (!compl) {
					LOG.error('initFormMEH> problème de définition de la completion MEH.');
				}
			}
			catch (e3) {
				LOG.error('initFormMEH> problème de définition de la completion MEH : ' + e3);
			}
		}

		var submitMEH = getElementById('submitMEH');
		if (submitMEH && submitMEH.type == 'button') {
			addJavascriptToAttribute(submitMEH, 'onclick', 'submitFormMEH();');
		}

		initDates();
		WIN.verifyFormMEH(false);

		// [bfoucher] : permet de remettre le bouton de recherche du formulaire dans son état initial dans le cas où la page est rechargée
		var body = DOC.getElementsByTagName('BODY')[0];
		addJavascriptToAttribute(body, 'onunload', 'resetSubmitMEHButton');
		flagInitFormMEH = true;
	};

	/**
	 * Initialise le lieu avec un texte par défaut.
	 **/
	WIN.initMEHLieu = function(lieu, code) {
		// FIXME checks de lieuIataMEH à supprimer, c'est pour la compatibilité avec les anciens termes 'iata' au lieu de 'data'
		var eltLieuText = getElementById('lieuMEH'),
				eltLieuData = getElementById('lieuDataMEH') || getElementById('lieuIataMEH');
		if (eltLieuText && lieu) {
			eltLieuText.value = lieu;
		}

		if (eltLieuData) {
			if (code) {
				eltLieuData.value = code;
			} else if (lieu) {
				eltLieuData.value = lieu;
			}
		}
	};

	/**
	 * Initialise le nombre de chambre, adultes, enfants.
	 **/
	WIN.initMEHChambrePax = function(chambres, paxAdultes, paxEnfants) {
		//var eltPaxMEHAdultes=getElementById("paxMEHAdultes"),
		//eltPaxMEHEnfants=getElementById("paxMEHEnfants");
		// FIXME pour compatibilite ascendente
		var eltPaxMEHAdultes = getElementById('paxMEHAdultes') || getElementById('paxAdultes'),
				eltPaxMEHEnfants = getElementById('paxMEHEnfants') || getElementById('paxEnfants');
		var eltChambres = getElementById('chambres');


		if (eltChambres && chambres) {
			eltChambres.value = chambres;
		}
		if (eltPaxMEHAdultes && paxAdultes) {
			eltPaxMEHAdultes.value = paxAdultes;
		}
		if (eltPaxMEHEnfants && paxEnfants) {
			eltPaxMEHEnfants.value = paxEnfants;
		}
	};

	/**
	 * Cette méthode doit correspondre à la soumission réelle du formulaire.
	 * @param {!Element} f formulaire à soumettre.
	 * Elle peut être surchargée si besoin.
	 */
	WIN.doSubmitFormMEH = function(f) {
		if (f) {
			try {
				f.submit();
			}
			catch (e) {
			}
		}
	};

	var RE_HOST = new RegExp('www[.](easyvoyage[.]com||easyviajar.com||easyviaggio[.]com||easyvoyage[.]co[.]uk||easyvoyage[.]de)');

	/**
	 * Cette fonction vérifie la cohérence des données, et le cas échéant soumet le formulaire formMEH
	 * Elle ajoute la classe wait à submitMEH pour permettre l'affichage d'une image de chargement.
	 * MAJ :
	 * Pour un code plus propre, depuis août 2010, les textes insérés dans une image sont proscrits.
	 * On profite donc de la classe wait pour aligner le texte et non plus pour charger une image de chargement.
	 * la fonction dot3 permet l'affichage des trois petits points après le texte "En cours".
	 *
	 * FIXME :
	 * Comme le changement implique de retoucher au CSS des affiliés (1100 form à vérifier/corriger), il a été décidé
	 * de n'executer ce code que dans l'environnement ESV, ce qui exclu les affiliés.
	 * TODO : Il faudra supprimer le test du "window.location.host" et vérifier les affiliations.
	 **/
	WIN.submitFormMEH = function() {
		if (!WIN.verifyFormMEH(true)) { return false; }
		var submitMEH = getElementById('submitMEH');
		addClass(submitMEH, 'wait');
		if (submitMEH.value && RE_HOST.test(WIN.location.host)) {
			EASY.fx.dot3(submitMEH, 'value', waitValueSubmitME);
		}
		errorMEH = false;
		WIN.doSubmitFormMEH(getElementById('formMEH'));
		return true;
	};

	WIN.resetSubmitMEHButton = function() {
		var submitMEH = getElementById('submitMEH');
		removeClass(submitMEH, 'wait');
		if (submitMEH.value) {
			if (typeof submitMEH.stopDot3 == 'function') {
				submitMEH.stopDot3(submitValueSubmitME);
			}
			submitMEH.value = submitValueSubmitME;
		}
	};

	WIN.setActionMEH = function(dir) {
		getElementById('formMEH').setAttribute('action', dir);
	};

	WIN.setTargetFormMEH = function(targetForm) {
		getElementById('formMEH').setAttribute('target', targetForm);
		EASY.meh.Context().setTarget(targetForm);
	};

	// traductions du paramètre 'lieu'
	var MAPPINGS_LIEU = [
		{lang: 'fr_FR', param: 'arrivee'},
		{lang: 'es_ES', param: 'destino'},
		{lang: 'it_IT', param: 'destinazione'},
		{lang: 'en_GB', param: 'arrival'},
		{lang: 'de_DE', param: 'ankunft'}
	];

	function realReadURL() {
		var clientIdValue = EASY.tools.getParameter('clientId');
		if (clientIdValue) {
			var inputs = EASY.dom.tags('input', getElementById('formMEH'));
			var cnt = inputs.length;
			for (var i = 0; i < cnt; ++i) {
				if (inputs[i].name === 'clientId') {
					inputs[i].value = clientIdValue;
				}
			}
		}

		// FIXME checks de lieuIataMEH à supprimer, c'est pour la compatibilité avec les anciens termes 'iata' au lieu de 'data'
		var eltLieuText = getElementById('lieuMEH'),
				eltLieuData = getElementById('lieuDataMEH') || getElementById('lieuIataMEH');

		// Remplissage des champs gérant le lieu de départ (s'il existent)
		if (eltLieuText) {
			autoFillLieuFromUrl(eltLieuText, eltLieuData, MAPPINGS_LIEU, 'MEH');
		}
	}

	/**
	 * Cette fonction effectue le préchargement des champs de formulaire du form MEH en fonction
	 * des paramètres d'URL associés.
	 **/
	WIN.readURLMEH = function() {
		// On remplace la fonction pour que le process ne se fasse qu'une fois (en cas d'appel multiple)
		WIN.readURLMEH = function() {
			warnMsg('formMEH#readURLMEH(): URL déjà interprétée!');
		};

		// Première interprétation des paramètres de l'URL
		realReadURL();
	};
}()); // exécution fonction anonyme ici

