

(function() {
	var window = this,
			ev = window.ev,
			Date = window.Date,
			addJavascriptToAttribute = window.addJavascriptToAttribute,
			initJours = window.initJours,
			initMois = window.initMois,
			Calendar = window.Calendar,
			isValidDate = window.isValidDate,
			createDate = window.createDate,
			genericNavigator = window.genericNavigator,
			// raccourci vers window.ev.meh
			MEH,
			// raccourci vers window.ev.dom.element
			element = ev.dom && ev.dom.element;

	if (!ev) { throw 'mev.searchHistoryManager#<init>: Needs ev.core module!'; }
	if (!element) {throw new Error("La fonction 'ev.dom.element(id)' doit exister");}
	// On s'assure que le namespace ev.meh existe
	if (!ev.meh) { ev.meh = {}; }

	MEH = ev.meh;
	/**
	 * Surcharge de la methode de soumission de formulaire.
	 * @param {Element} f formulaire a soumettre.
	 *
	 * Convertir les valeurs du formulaire en criteres de recherche
	 * Puis lancer une timeline setCritere (qui lance la recherche)
	 */
	MEH.doSubmitFormMEH3 = function(f) {
		try {
			ev.log.info('Définition des criteres...');
			// définition des criteres de recherche
			var criteres = MEH.Context().getCriteres(),
					urlPageResultats = '?',
					lieuIataMEHValue = element('lieuIataMEH').value,
					lieuMEHValue = element('lieuMEH').value,
					jourDebutMEH = element('jourDebutMEH').value,
					moisDebutMEH = element('moisDebutMEH').value,
					jourFinMEH = element('jourFinMEH').value,
					moisFinMEH = element('moisFinMEH').value,
					eltPaxMEHAdultes = element('paxMEHAdultes') || element('paxAdultes'),
					eltPaxMEHEnfants = element('paxMEHEnfants') || element('paxEnfants'),
					myDateDebut = jourDebutMEH + '/' + moisDebutMEH,
					myDateFin = jourFinMEH + '/' + moisFinMEH;

			if (lieuIataMEHValue) {
				criteres.ville = lieuIataMEHValue;
			}
			else {
				criteres.ville = lieuMEHValue;
			}
			//criteres.lieu = lieuMEHValue;
			criteres.dateDebut = myDateDebut;//.replace(/\//g,"-");
			criteres.dateFin = myDateFin;//.replace(/\//g,"-");
			criteres.chambres = element('chambres').value;
			criteres.paxAdultes = eltPaxMEHAdultes.value;
			criteres.paxEnfants = eltPaxMEHEnfants.value;
			criteres.etoiles = element('etoiles').value;

			// gestion de l'URL de destination (resultats)
			urlPageResultats = urlPageResultats + 'ville=' + criteres.ville;
			//urlPageResultats = urlPageResultats + "&lieu=" + criteres.lieu;
			urlPageResultats = urlPageResultats + '&dateDebut=' + Date.convertSelectorToStringFr('jourDebutMEH', 'moisDebutMEH');
			urlPageResultats = urlPageResultats + '&dateFin=' + Date.convertSelectorToStringFr('jourFinMEH', 'moisFinMEH');
			urlPageResultats = urlPageResultats + '&chambres=' + element('chambres').value;
			urlPageResultats = urlPageResultats + '&paxAdultes=' + eltPaxMEHAdultes.value;
			urlPageResultats = urlPageResultats + '&paxEnfants=' + eltPaxMEHEnfants.value;
			urlPageResultats = urlPageResultats + '&etoiles=' + element('etoiles').value;
			//ligne çi dessous à décommenter pour atteindre la page de résultats par url sans mettre les critères dans la sessions
			ev.log.info('URL : ' + MEH.Context().PAGE_RESULTS);
			if (new RegExp('/hotels/resultats|/hoteles/resultados|/hotel/resultats|/hotels/results|/hotels/ergebnisse|meh3/results.jsp').test(MEH.Context().PAGE_RESULTS)) {
				ev.log.info('MEH 3.5 : ' + MEH.Context().PAGE_RESULTS + urlPageResultats);
				window.location = MEH.Context().PAGE_RESULTS + urlPageResultats;
			}
			else {
				try {
					ev.log.warn('MEH 3.0');
					MEH.Context().setCriteres();
				}
				catch (errorOnSubmit3) {
					ev.log.error('Erreur sur le Submit du Form MEH (set criteres) : ' + errorOnSubmit3);
				}
			}
		}
		catch (errorOnSubmit) {
			ev.log.error('Erreur sur le Submit du Form MEH : ' + errorOnSubmit);
		}
		return false;
	};
	MEH.launchSearchWithParams = function(dateDebut, dateFin, ville, paxAdultes, paxEnfants) {
		// définition des criteres de recherche
		var criteres = MEH.Context().getCriteres();
		criteres.ville = ville;
		criteres.paxAdultes = paxAdultes;
		criteres.paxEnfants = paxEnfants;
		criteres.dateDebut = dateDebut;
		criteres.dateFin = dateFin;
		MEH.Context().setCriteres();
	};
	/**
	 * Initialise une pile de formulaire pour la placer sur le formulaire MEH
	 * Et préparer la soumission du formulaire
	 */
	MEH.setFormMEH = function() {
		/**
		 * Surcharge de la méthode de soumission de formulaire.
		 * @param {Element} f formulaire à soumettre.
		 */
		window.doSubmitFormMEH = function(f) {
			MEH.doSubmitFormMEH3(f);
			return false;
		};
		ev.log.info('Formulaire MEH3 pret !');
	};
	var cdataRegex = new RegExp(/<!\[CDATA\[([^\]]*)\]\]>/);
	/**
	 * expression rationnelle pour extraire le contenu d'une balise XML prï¿½fixï¿½e par CDATA
	 */
	MEH.stripCDATA = function(expression) {
		var content = cdataRegex.exec(expression);
		return content ? content[1] : expression;
	};
	/**
	 * permet d'initailaiser les petits formulaire de ME1H
	 **/
	MEH.initFormME1H = function(_idItem) {
		var formMEH = element('formMEH_' + _idItem);
		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 jourDebutMEH = element('jourDebutMEH_' + _idItem);
		var moisDebutMEH = element('moisDebutMEH_' + _idItem);
		var jourFinMEH = element('jourFinMEH_' + _idItem);
		var moisFinMEH = element('moisFinMEH_' + _idItem);
		var calendrierMEHDebutIcon = element('calendrierMEHDebutIcon_' + _idItem);
		var calendrierMEHFinIcon = element('calendrierMEHFinIcon_' + _idItem);
		var calendrierMEHDebut = element('calendrierMEHDebut_' + _idItem);
		var calendrierMEHFin = element('calendrierMEHFin_' + _idItem);
		initJours(jourDebutMEH);
		initMois(moisDebutMEH);
		initJours(jourFinMEH);
		initMois(moisFinMEH);
		if (jourDebutMEH && moisDebutMEH && calendrierMEHDebutIcon && calendrierMEHDebut) {
			try {
				var calendarMEHdebut = new Calendar(jourDebutMEH, moisDebutMEH, calendrierMEHDebut);
				addJavascriptToAttribute(calendrierMEHDebutIcon, 'onclick', 'calendarPool.get(' + calendarMEHdebut.poolIndex + ').show(this);');
			}
			catch (e) {
			}
		}
		if (jourFinMEH && moisFinMEH && calendrierMEHFinIcon && calendrierMEHFin) {
			try {
				var calendarMEHFin = new Calendar(jourFinMEH, moisFinMEH, calendrierMEHFin);
				addJavascriptToAttribute(calendrierMEHFinIcon, 'onclick', 'calendarPool.get(' + calendarMEHFin.poolIndex + ').show(this);');
			}
			catch (e2) {
			}
		}

		MEH.initME1HDates(_idItem);
		MEH.verifyFormME1H(_idItem);
	};
	/**
	 * Initialise les dates par défaut en utilisant l'horloge du client, la règle est la suivante pour la date début: c'est le
	 * prochain vendredi jusqu'au mercredi, et le vendredi en 8 à partir du jeudi. La date de fin est le jour suivant
	 * la date de début (par défaut on a une nuit).
	 * 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
	 **/
	var JOUR = 24 * 60 * 60 * 1000;
	MEH.initME1HDates = function(_idItem,dateDebutTexte,dateFinTexte) {
		var jourDebutMEH = element('jourDebutMEH_' + _idItem);
		var moisDebutMEH = element('moisDebutMEH_' + _idItem);
		var jourFinMEH = element('jourFinMEH_' + _idItem);
		var moisFinMEH = element('moisFinMEH_' + _idItem);
		if (!jourDebutMEH || !moisDebutMEH || !jourFinMEH || !moisFinMEH) { return; }

		var jourDebut,
				moisDebut,
				anneeDebut,
				jourFin,
				moisFin,
				anneeFin;

		var now = new Date();
		var day = now.getDay();
		var delta = 5 - day;
		if (delta <= 1) { delta += 7; }
		var dateDebut = new Date(),
				dateFin = new Date();
		dateDebut.setTime(now.getTime() + (delta * JOUR));
		dateFin.setTime(dateDebut.getTime() + (JOUR));

		if (dateDebutTexte && dateDebutTexte.match(/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/)) {
			jourDebut = dateDebutTexte.replace(/\/[0-9]{2}\/[0-9]{4}$/, '');
			moisDebut = dateDebutTexte.replace(/^[0-9]{2}\//, '');
		}
		else {
			jourDebut = '' + dateDebut.getDate();
			if (dateDebut.getDate() < 10) { jourDebut = '0' + dateDebut.getDate(); }
			moisDebut = '' + (dateDebut.getMonth() + 1);
			if (dateDebut.getMonth() < 9) { moisDebut = '0' + (dateDebut.getMonth() + 1); }
			moisDebut += '/' + dateDebut.getFullYear();
		}

		if (dateFinTexte && dateFinTexte.match(/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/)) {
			jourFin = dateFinTexte.replace(/\/[0-9]{2}\/[0-9]{4}$/, '');
			moisFin = dateFinTexte.replace(/^[0-9]{2}\//, '');
		}
		else {
			jourFin = '' + dateFin.getDate();
			if (dateFin.getDate() < 10) {jourFin = '0' + dateFin.getDate(); }
			moisFin = '' + (dateFin.getMonth() + 1);
			if (dateFin.getMonth() < 9) {moisFin = '0' + (dateFin.getMonth() + 1); }
			moisFin += '/' + dateFin.getFullYear();
		}
		jourDebutMEH.value = jourDebut;
		moisDebutMEH.value = moisDebut;
		jourFinMEH.value = jourFin;
		moisFinMEH.value = moisFin;
	};

	/**
	 * 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
	 **/
	MEH.verifyFormME1H = function(_idItem) {
		var error = false;
		var errorMEHDateDebutErronee = element('errorMEHDateDebutErronee_' + _idItem);
		var jourDebutMEH = element('jourDebutMEH_' + _idItem).value;
		var moisDebutMEH = element('moisDebutMEH_' + _idItem).value.replace(/\/[0-9]{4}$/, '');
		var anDebutMEH = element('moisDebutMEH_' + _idItem).value.replace(/^[0-9]{2}\//, '');
		if (isValidDate(jourDebutMEH, moisDebutMEH, anDebutMEH)) {
			if (errorMEHDateDebutErronee) { errorMEHDateDebutErronee.style.display = 'none'; }
		}
		else {
			if (errorMEHDateDebutErronee) { errorMEHDateDebutErronee.style.display = ''; }
			error = true;
		}
		var errorMEHDateFinErronee = element('errorMEHDateFinErronee_' + _idItem);
		var jourFinMEH = element('jourFinMEH_' + _idItem).value;
		var moisFinMEH = element('moisFinMEH_' + _idItem).value.replace(/\/[0-9]{4}$/, '');
		var anFinMEH = element('moisFinMEH_' + _idItem).value.replace(/^[0-9]{2}\//, '');
		if (isValidDate(jourFinMEH, moisFinMEH, anFinMEH)) {
			if (errorMEHDateFinErronee) { errorMEHDateFinErronee.style.display = 'none'; }
		}
		else {
			if (errorMEHDateFinErronee) { errorMEHDateFinErronee.style.display = ''; }
			error = true;
		}
		var errorMEHDatesInversees = element('errorMEHDatesInversees_' + _idItem);
		if (!error) {
			var dateDebutMEH = createDate(jourDebutMEH, moisDebutMEH, anDebutMEH);
			var dateFinMEH = createDate(jourFinMEH, moisFinMEH, anFinMEH);
			if (dateDebutMEH.getTime() < dateFinMEH.getTime()) {
				if (errorMEHDatesInversees) { errorMEHDatesInversees.style.display = 'none'; }
			}
			else {
				if (errorMEHDatesInversees) { errorMEHDatesInversees.style.display = ''; }
				error = true;
			}
		}
		else {
			if (errorMEHDatesInversees) { errorMEHDatesInversees.style.display = 'none'; }
		}

		return !error;
	};
	/**
	 *function urlToIndexedArray()
	 *converti une URL de la forme xxx.domaine.aaa?param_1=valeur_1&param_i=valeur_i
	 *en un tableau à deux dimension [[param_1, valeur_1], ...,[param_i, valeur_i]]
	 */
	MEH.urlToIndexedArray = function() {
		if (window.location.search.substring(1)) {
			var url = window.location.search.substring(1).split('&');
			//insuffisant : il faut tester la validité de l'url et "échapper" les variables pour ne pas y insérer du code javascript
			//tester la longueur de l'url, le nombre de paramètre ... avant de faire le traitement çi dessous
			var i = url.length;
			if (i > 7) {//on fixe une limite du nombre de paramètre dans l'url
				return false;
			} // on teste que la table ne soit pas d'une longueur démesurée avant de la traiter
			else {
				var paramIndexedHashMap = [];
				while (i--) {
					var attribut = (url[i].split('='))[0];//la valeur a gauche du signe '=' est la clé
					var valeur = (url[i].split('='))[1];//la valeur a droite du signe '=' est la valeur
					paramIndexedHashMap[i] = [attribut, valeur];
				}
				return paramIndexedHashMap;
			}
		}
		else {
			return false;
		}
	};

	/**
	 *function indexedArrayToAssociativeArray(paramHashMap)
	 *transforme un tableau indexé [[param_1, valeur_1], ...,[param_i, valeur_i]] en un tableau associatif {clé : valeur} ou clé = param_i et valeur = valeur_i
	 *les paramètres doublons sont supprimés selon leur ordre d'apparition dans le tableau indexé : seul le doublon à l'index le plus faible est conservé
	 */
	MEH.indexedArrayToAssociativeArray = function(paramHashMap) {
		if (paramHashMap) {
			var i = paramHashMap.length;
			var uniqueHashMap = [];
			while (i--) {
				uniqueHashMap[paramHashMap[i][0]] = paramHashMap[i][1];
				ev.log.info('paramHashMap[i][0] : ' + paramHashMap[i][0] + ' | paramHashMap[i][1] : ' + paramHashMap[i][1]); }
			return (uniqueHashMap);
		} else {
			return false;
		}
	};

	/**
	 *function urlToAssociativeArray()
	 *converti une URL de la forme xxx.domaine.aaa?param_1=valeur_1&param_i=valeur_i
	 *en un tableau associatif {clé : valeur} ou clé = param_i et valeur = valeur_i
	 *les paramètres doublons sont supprimés selon leur ordre d'apparition dans l'url : seul le doublon apparaissant en premier dans l'url est conservé
	 */
	MEH.urlToAssociativeArray = function() {
		return MEH.indexedArrayToAssociativeArray(MEH.urlToIndexedArray());
	};
	/**
	 *function testIndexedArray(paramHashMap)
	 *effectue une série de tests sur les valeurs d'un tableau à deux dimensions [[param_1, valeur_1], ...,[param_i, valeur_i]]
	 *les tests sont appliqués à toutes les valeurs du tableaux, même si il existe des doublons dans les paramètres (par exemple :
	 *[['param_1', 'hello'],['param_1', 'world']]
	 */
	MEH.testUrlMEH = function(paramHashMap) {
		if (paramHashMap) {
			var indicesErreur = [];
			//une date de fin dans l'URL implique qu'il y ait une date de début :
			if (paramHashMap.dateFin && !paramHashMap.dateDebut) {
				indicesErreur.push('date de debut manquante');
			}
			//une date de début dans l'URL implique qu'il y ait une date de fin :
			else if (paramHashMap.dateDebut && !paramHashMap.dateFin) {
				indicesErreur.push('date de fin manquante');
			}
			else {
				for (var cle in paramHashMap) {
					if (paramHashMap.hasOwnProperty(cle)) {
						switch (cle) {
							case 'lieu':
								//insérer ici les instructions de test sur le champ "ville"
								break;
							case 'paxAdultes':
								//insérer ici les instructions de test sur le champ "paxAdultes"
								break;
							case 'paxEnfants':
								//insérer ici les instructions de test sur le champs "paxEnfants"
								break;
							case 'chambres':
								//insérer ici les instructions de test sur le champ "chambres"
								break;
							case 'etoiles':
								//insérer ici les instructions de test sur le champ "etoiles"
								break;
							case 'dateDebut':
								//insérer ici les instructions de test sur le champ "dateDebut"
								break;
							case 'dateFin':
								//insérer ici les instructions de test sur le champ "dateFin"
								break;
							default:
								indicesErreur.push('le paramètre ' + cle + " n'est pas géré");//si un parametre de l'url n'est pas dans les cas ci dessus alors elle est incorrecte
								break;
						}
					}
				}
			}
			if (indicesErreur.length > 0) {
				ev.log.error(indicesErreur);// si un test n'a pas été effectué avec succès ...
				return false;
			} else {//si tous les tests sont OK ...
				return true;
			}
		}
		else {
			return false;
		}
	};


	/**
	 * cette methode va permettre de lancer un recherche a partir des paramètre de l'url
	 */
	MEH.launchSearchWithUrlParams = function() {
		var urlAssociativeArray = MEH.urlToAssociativeArray();
		if (MEH.testUrlMEH(urlAssociativeArray))//si l'URL est correcte on créé l'objet critere associé
		{
			var criteres = MEH.Context().getCriteres();
			//TODO bloc ci dessous à remplacer par une fonction associativeArrayToCritere()
			criteres.ville = urlAssociativeArray.lieu;//on passera ici directement l'id de la ville
			criteres.paxAdultes = urlAssociativeArray.paxAdultes;
			criteres.paxEnfants = urlAssociativeArray.paxEnfants;
			criteres.chambres = urlAssociativeArray.chambres;
			criteres.etoiles = urlAssociativeArray.etoiles;
			criteres.dateDebut = urlAssociativeArray.dateDebut;
			criteres.dateFin = urlAssociativeArray.dateFin;

			MEH.SetCriteresMethod(MEH.Context().getEraPath_recherche('') + '/criteres/creer.rjs?' + criteres.inUrlParams(), criteres, function() {}); // une fois le critère généré on l'injecte  dans la session

			return true;
		}
		else { //sinon on renvoie une 404
			return false;
		}
	};

	/**
	 * esvId=false&ville=Londres&dateDebut=12-10-2010&dateFin=13-10-2010
	 * esvId=false&ville=undefined&dateDebut=12-10-2010&dateFin=13-10-2010
	 * Recuperation des parametres de l'url + initialisation des parametres manquant
	 */
	MEH.launchSeachWithDeepLink = function() {
		if (window.location.search.substring(1)) {
			var url = window.location.search.substring(1).split('&');
			if (url.length > 7) {
				return false;
			}
			else {
				var nbElt = url.length;
				var params = [];
				while (nbElt--) {
					var attribut = (url[nbElt].split('='))[0];//la valeur a gauche du signe '=' est la clé
					var valeur = (url[nbElt].split('='))[1];//la valeur a droite du signe '=' est la valeur
					params[attribut] = valeur;
				}
				var criteres = MEH.Context().getCriteres();

				/** Parametre Obligatoire */
				criteres.ville = params.lieu;//on passera ici directement l'id de la ville
				if (criteres.ville == 'undefined') {
					return false;
				}

				/** Parametre NON-Obligatoire */
				criteres.paxAdultes = params.paxAdultes;
				if (!criteres.paxAdultes) {criteres.paxAdultes = 2;}

				criteres.paxEnfants = params.paxEnfants;
				if (!criteres.paxEnfants) {criteres.paxEnfants = 0;}

				criteres.chambres = params.chambres;
				if (!criteres.chambres) {criteres.chambres = 1;}

				criteres.etoiles = params.etoiles;
				if (!criteres.etoiles) {criteres.etoiles = 0;}

				//Genere les bonnes date de recherche
				var aujourdhui = new Date();
				var numNomJour = aujourdhui.getDay();
				var numVendredi = 5;
				var timeJour = 24 * 60 * 60 * 1000;
				//vendredi dans +-3semaine
				var timeDans1semaineDebut = aujourdhui.getTime() + (7 + (numVendredi - numNomJour)) * timeJour;
				var dans1semaineArrivee = new Date(timeDans1semaineDebut);
				//Jour suivant
				var timeDans1semaineFin = timeDans1semaineDebut + timeJour;
				var dans1semaineDepart = new Date(timeDans1semaineFin);

				criteres.dateDebut = dans1semaineArrivee.getDate() + '/' + (dans1semaineArrivee.getMonth() + 1) + '/' + dans1semaineArrivee.getFullYear();
				criteres.dateFin = dans1semaineDepart.getDate() + '/' + (dans1semaineDepart.getMonth() + 1) + '/' + dans1semaineDepart.getFullYear();

				MEH.SetCriteresMethod(MEH.Context().getEraPath_recherche('') + '/criteres/creer.rjs?' + criteres.inUrlParams(), criteres, function() {}); // une fois le critère généré on l'injecte  dans la session

				return true;
			}
		}
		else {
			return false;
		}
	};
}());

