

(function() {
	var window = this,
			ev = window.ev,
			document = window.document,
			Date = window.Date;

	if (!ev) { throw 'mev.searchHistoryManager#<init>: Needs ev.core module!'; }
	if (!ev.rjs) {throw new Error("Le namespace 'ev.rjs' doit exister");}
	// On s'assure que le namespace ev.meh existe
	if (!ev.meh) { ev.meh = {}; }
	//Si la classe Context est définie on sort
	if (ev.meh.Context) {return;}

	// on teste d'abord l'existance des classes nécessaires
	window.Classe.checkDefined('ev.me.Compte');
	window.Classe.checkDefined('ev.me.SetCompteMethod');
	window.Classe.checkDefined('ev.meh.Criteres');
	window.Classe.checkDefined('ev.meh.SetCriteresMethod');
	window.Classe.checkDefined('ev.meh.GetCriteresMethod');
	// on teste ensuite l'existance du namespace ev.meh.Recherche
	if (!ev.meh.Recherche) {throw new Error("Le namespace 'ev.meh.Recherche' n'est pas défini!");}

	// Initialisation des chemins utiles
	var enginePath = '/hotels',
			searchPath = enginePath + '/recherche/MEH',
			criterListener = [],
			PAGE_RESULTS = 'result.html';

	function addCriteresListener(listener) {
		criterListener.push(listener);
	}

	function fireCritereEvent(cr) {
		//alert('fire'+cr.toString());
		for (var i = 0; i < criterListener.length; i++) {
			criterListener[i].onCriteresReceived(cr);
		}
	}

	var target = '',
			compte = new ev.me.Compte(),
			criteres = new ev.meh.Criteres(),
			rjsLocator = new ev.rjs.Locator(30000),
			// Expression régulière représentant la clé crikey d'un jeu de criteres
			// ex : Criteres{idVille,dateDebut,dateFin,nbChambres,nbEtoiles,paxAdultes,paxEnfants}
			REGEXP_ID_VILLE = /Criteres[{]([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^}]+)[}]/;

	/**
	 * Utilisation du jeu de criteres, une fois
	 * qu'il est récupéré et démarrage recherche.
	 */
	function onCriteresRetreived() {
		fireCritereEvent(criteres);
		// lancement de la recherche
		ev.meh.Recherche.startRecherche();
		ev.meh.Context().initForm();
	}

	/**
	 * Method appelée quand les critères ont été enregistrés.
	 */
	function onCriteresRecorded() {
		ev.log.info('criteres recorded : ' + criteres.toString());
		ev.log.debug('Ouverture page resultats...');
		// Envoi vers page de résultats avec encodage de l'URL (pour être sûr d'avoir la session ERA sur la page suivante)
		//FIXME à valider
		if (target === '_blank') {//on ouvre la page de résultat dans un nouvel onglet (pour les affiliés)
			window.open(ev.requestManager.encodeAnchor(PAGE_RESULTS), '_blank');
		}
		else {
			window.location.href = ev.requestManager.encodeAnchor(PAGE_RESULTS);
			//        window.location.href=PAGE_RESULTS;
		}
	}

	/**
	 * Raccourci au cas où c'est utilisé à l'extérieur.
	 */
	function onCompteRecorded() {
		ev.log.info('compte recorded : ' + compte.toString());
	}

	/**
	 * Méthode privée permettant d'effectuer la requête réelle
	 * d'enregistrement du compte vers le serveur.
	 */
	function recordCompte() {
		ev.log.info('recordCompte() - compte: ' + compte.toString());
		// FIXME [ygally] SetCompteMethod() devrait être une méthode et pas un contructeur
		var setCompteMethod = new ev.me.SetCompteMethod(enginePath + '/compte/choisir.rjs?urlInfos=infos.jsp', compte, onCompteRecorded);
	}

	/**
	 * Classe permettant de stoker les informations
	 * générales du moteur MEH3.
	 *
	 * @constructor
	 */
	function Context() {
		// FIXME à supprimer !
		this.BASE_XML = '/rjs/meh';

		this.PAGE_INDEX = 'formulaire.html';
		this.PAGE_RESULTS = PAGE_RESULTS;
		this.PAGE_INFOS = 'infos.html';

		/**
		 * Permet de récuperer la clé crikey dans un jeu de criteres
		 * @param {string} cr Jeu de criteres.
		 */
		this.getIdVille = function(cr) {
			var idVille = 0;
			if (REGEXP_ID_VILLE.test(cr)) {
				// on récupère le groupe correspondant à l'id de la ville dans la clé des critères
				idVille = RegExp.$1;
				ev.log.info('ev.meh.Context().getIdVille() > idVille : "' + idVille + '"');
			}
			else {
				ev.log.error('ev.meh.Context().getIdVille() > No idVille in criteres!');
			}
			return idVille;
		};

		/**
		 * Surcharge pour le vol.
		 * @param {Object} method chemin de la méthode à appeler
		 *   sur le service de recherche (ERA).
		 */
		this.getEraPath_recherche = function(method) {
			return searchPath + method;
		};

		/**
		 * Permet de récupérer le compte courant de la page.
		 */
		this.getCompte = function() {
			return compte;
		};

		/**
		 * Permet de récupérer les critères courant de la page.
		 */
		this.getCriteres = function() {
			return criteres;
		};

		/**
		 * Permet de récupérer la valeur de la variable target
		 */
		this.getTarget = function() {
			return target;
		};

		/**
		 * Retourne le gestionnaire de RJS global.
		 */
		this.getRjsLocator = function() {
			return rjsLocator;
		};

		/**
		 * Permet de récupérer le jeu de criteres courant de la page
		 * et de lancer la recherche.
		 * NB : Ne doit être appelée qu'une seule fois.
		 */
		this.lancerRecherche = function() {
			ev.log.info('ev.meh.Context.lancerRecherche() - criteres: ' + criteres.toString());
			// FIXME [ygally] SetCriteresMethod() devrait être une méthode et pas un contructeur
			var setCriteresMethod = new ev.meh.SetCriteresMethod(searchPath + '/criteres.rjs', criteres, onCriteresRetreived);
		};

		/**
		 * permet de lancer la recherche soit a partir des parametres presents dans l'url soit a partir des criteres settés en session
		 */
		this.launchSearch = function() {
			var getCriteresMethod;
			ev.log.error('ev.meh.Context.launchSearch() - criteres: ' + criteres.toString());
			if (ev.meh.launchSearchWithUrlParams()) {
				// on lance la recherche à partir des parametres contenus dans l'url
				//ev.meh.Recherche.startRechercheWithCritere(ev.meh.Context().getCriteres());// on lance la recherche
				// FIXME [ygally] GetCriteresMethod() devrait être une méthode et pas un contructeur
				getCriteresMethod = new ev.meh.GetCriteresMethod(searchPath + '/criteres.rjs', criteres, onCriteresRetreived);
			}
			else if (ev.meh.launchSeachWithDeepLink())
			{
				// FIXME [ygally] GetCriteresMethod() devrait être une méthode et pas un contructeur
				getCriteresMethod = new ev.meh.GetCriteresMethod(searchPath + '/criteres.rjs', criteres, onCriteresRetreived);
			}
			else {
				// on lance la recherche à partir des criteres settés dans la session auparavant
				// FIXME [ygally] GetCriteresMethod() devrait être une méthode et pas un contructeur
				getCriteresMethod = new ev.meh.GetCriteresMethod(searchPath + '/criteres.rjs', criteres, onCriteresRetreived);
			}
		};

		this.addCriteresListener = function(listener) {
			// test si criteres deja recupérés
			if (criteres) {
				listener.onCriteresReceived(criteres);
			}
			addCriteresListener(listener);
		};

		//ev.meh.Context.addCriteresListener=;

		/**
		 * Méthode qui permet de générer un JS pour le tracking xiti en Multicriteres.
		 */
		this.xitiMultiC = function(criteres,idPage) {
			var dateDebut = criteres.dateDebut.getFullYear() + (criteres.dateDebut.getMonth() < 9 ? '0' : '') + (criteres.dateDebut.getMonth() + 1) + criteres.dateDebut.getDate();
			var dateFin = criteres.dateFin.getFullYear() + (criteres.dateFin.getMonth() < 9 ? '0' : '') + (criteres.dateFin.getMonth() + 1) + criteres.dateFin.getDate();
			//variable multi-critere
			window.ev.xiti = '&x1=' + idPage + '&x2=&x3=' + dateDebut + '&x4=' + dateFin + '&x5=' + ev.meh.Context().getIdVille(criteres) + '&x6=&x7=' + criteres.getNbEtoiles() + '&x8=' + criteres.getNbChambres() + '&x9=' + criteres.getNbPaxAdultes() + '&x10=' + criteres.getNbPaxEnfants() + '&x11=&x12=';
		};

		this.initForm = function() {
			ev.log.debug('ev.meh.Context.initForm() - criteres: ' + criteres.toString());
			// Alimenter le formulaire à partir de l'objet
			if (document.getElementById('lieuMEH')) {
				document.getElementById('lieuMEH').value = criteres.ville;
			}
			if (document.getElementById('jourDebutMEH') && document.getElementById('moisDebutMEH')) {
				Date.convertDateToSelector(criteres.dateDebut, 'jourDebutMEH', 'moisDebutMEH');
			}
			if (document.getElementById('jourFinMEH') && document.getElementById('moisFinMEH')) {
				Date.convertDateToSelector(criteres.dateFin, 'jourFinMEH', 'moisFinMEH');
			}
			function dateToString(_date) {
				var d = _date.getDate(), m = _date.getMonth() + 1, y = _date.getFullYear();
				if (m < 10) {m = '0' + m;}
				return d + '/' + m + '/' + y;
			}
			function stringToDate(d,m,y) {
				var _date = new Date();
				_date.setDate(parseInt(d, 10));
				_date.setMonth(parseInt(m, 10) - 1);
				_date.setYear(parseInt(y, 10));
				return _date;
			}
			//
			window.initMEHDates(dateToString(criteres.dateDebut), dateToString(criteres.dateFin));
			if (document.getElementById('chambres')) {
				document.getElementById('chambres').value = criteres.chambres;
			}
			if (document.getElementById('paxAdultes')) {
				document.getElementById('paxAdultes').value = criteres.paxAdultes;
			}
			if (document.getElementById('paxEnfants')) {
				document.getElementById('paxEnfants').value = criteres.paxEnfants;
			}
			if (document.getElementById('etoiles')) {
				document.getElementById('etoiles').value = criteres.etoiles;
			}
		};

		/**
		 * FIXME
		 */
		this.setCriteres = function() {
			ev.log.info('Envoi des criteres...');
			// FIXME [ygally] SetCriteresMethod() devrait être une méthode et pas un contructeur
			var setCriteresMethod = new ev.meh.SetCriteresMethod(searchPath + '/criteres/creer.rjs?' + criteres.inUrlParams(), criteres, onCriteresRecorded);
		};

		/**
		 * Permet de choisir le chemin des pages XML.
		 * @param {String} _baseXML : chemin des XML.
		 *
		 * FIXME à supprimer !
		 */
		this.setBaseXML = function(_baseXML) {
			this.BASE_XML = _baseXML;
		};

		/**
		 * Permet de choisir le chemin de la page d'index.
		 * @param {String} _page : page d'index.
		 */
		this.setPageIndex = function(_page) {
			this.PAGE_INDEX = _page;
		};

		/**
		 * Permet de choisir le chemin de la page de resultats.
		 * @param {String} _page : page de resultats.
		 */
		this.setPageResults = function(_page) {
			this.PAGE_RESULTS = (PAGE_RESULTS = _page);
		};

		/**
		 * Permet de choisir le chemin de la page de redirection partenaire.
		 * @param {String} _page : page de redirection.
		 */
		this.setPageInfos = function(_page) {
			this.PAGE_INFOS = _page;
		};

		/**
		 * Permet de choisir le site et le code client
		 * du compte courant.
		 *
		 * Une fois les données fixées, cette méthode
		 * envoie la nouvelle définition de compte dans
		 * la session.
		 *
		 * @param {?number=} _site ID du site.
		 * @param {?number=} _codeClient code client du compte (si on souhaite utiliser le compte principal du site, ce paramètre est facultatif).
		 */
		this.setCompteBySiteAndCode = function(_site, _codeClient) {
			if (_site) {
				// init du compte à partir des paramètres donnés
				compte.setBySiteAndCode(_site, _codeClient);

				// envoi du compte au serveur (via timeline)
				recordCompte();
			}
		};
		/**
		 * Permet de choisir si la page de résultat s'ouvre dans une nouvelle fenêtre
		 *
		 * @param {?string=} _target attribut target de open.window.
		 */
		this.setTarget = function(_target) {
			if (_target) {
				target = _target;
			}
		};


		/**
		 * Permet de choisir le compte client courant à
		 * partir de son identifiant numérique.
		 *
		 * Une fois les données fixées, cette méthode
		 * envoie la nouvelle définition de compte dans
		 * la session.
		 *
		 * @param {?number=} _client : ID du compte client.
		 */
		this.setCompteByClient = function(_client) {
			if (_client) {
				// init du compte à partir du paramètre donné
				compte.setCompteByClient(_client);

				// envoi du compte au serveur (via timeline)
				recordCompte();
			}
		};

		// Raccourcis au cas où ils sont utilisés à l'extérieur.
		this.recordCompte = recordCompte;
		this.onCompteRecorded = onCompteRecorded;
		this.onCriteresRetreived = onCriteresRetreived;
		this.onCriteresRecorded = onCriteresRecorded;
	}

	// instanciation du singleton
	var singletonInstance = new Context();
	// raccourci patché vers la classe en singleton
	ev.meh.Context = function() {
		return singletonInstance;
	};

	ev.log.debug('ev/meh/Context.js ok');
}());

