

/**
 * La documentation de ce script n'est pas développée ici,
 * on fera référence à la documentation de completionMEV.js
 */
(function() {
	//'use strict';
	// Raccourci vers window
	var WIN = this,
			// Raccourci vers document
			DOC = WIN.document,
			// synonymes de true et false
			FALSE = !WIN, TRUE = !FALSE,
			// Raccourci vers window.ev
			EASY = WIN.ev,
			// Raccourci vers window.ev.log
			LOG = EASY && EASY.log,
			// Raccourci vers window.ev.dom
			DOM = EASY && EASY.dom,
			addClass = DOM && DOM.addClass,
			removeClass = DOM && DOM.removeClass,
			// Raccourci vers fonctions utiles
			setTimeout = WIN.setTimeout,
			addJavascriptToAttribute = WIN.addJavascriptToAttribute,
			genericNavigator = WIN.genericNavigator,
			MSIE = WIN.MSIE,

			completionMEHURLRoot,
			dn = EASY.path.cdn,
			texteHotel,
			completionMEHRJS,
			poolArray = [], completionPool;

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

	// Dimensions des lignes pour les MSIE<=6.9
	WIN.MSIE6_LINE_HEIGHT = 20;
	WIN.MSIE6_LINE_WIDTH = 300;

	switch (EASY.lang.current) {
		case 'es_ES':
			completionMEHURLRoot = dn + '/rjs/completion/MEH/es_ES';
			texteHotel = ' hoteles';
			break;
		case 'it_IT':
			completionMEHURLRoot = dn + '/rjs/completion/MEH/it_IT';
			texteHotel = ' hotel';
			break;
		case 'en_GB':
			completionMEHURLRoot = dn + '/rjs/completion/MEH/en_GB';
			texteHotel = ' hotels';
			break;
		case 'de_DE':
			completionMEHURLRoot = dn + '/rjs/completion/MEH/de_DE';
			texteHotel = ' hotels';
			break;
		//case 'fr_FR': // par défaut
		default:
			completionMEHURLRoot = dn + '/rjs/completion/MEH/fr_FR';
			texteHotel = ' hôtel(s)';
			break;
	}

	completionMEHRJS = new WIN.RemoteScript(completionMEHURLRoot + '/load_default.rjs');

	/**
	 * @constructor
	 */
	WIN.PropositionMEHVille = function(nom,pays,code,id,nbHotels) {
		var thisPropVille = this;
		thisPropVille.nom = nom;
		thisPropVille.pays = pays;
		thisPropVille.code = code;
		thisPropVille.id = id;
		if (id && code && code !== 'null') {
			thisPropVille.data = 'v:' + id + '|c:' + code + '|t:' + nom;
		}
		else if (id) {
			thisPropVille.data = 'v:' + id;
		}
		else if (code && code !== 'null') {
			thisPropVille.data = 'c:' + code;
		}
		else {
			thisPropVille.data = nom;
		}
		thisPropVille.div = DOC.createElement('DIV');
		thisPropVille.div.className = 'propositionVille';
		if (nbHotels) {
			thisPropVille.nbHotels = nbHotels;
			thisPropVille.div.appendChild(DOC.createTextNode(nom + ', ' + pays + ' (' + nbHotels + texteHotel + ')'));
		}else {
			thisPropVille.div.appendChild(DOC.createTextNode(nom + ', ' + pays));
		}
		thisPropVille.div.style.display = 'none';
		thisPropVille.index = -1;
		thisPropVille.keywords = [];
	};
	WIN.PropositionMEHVille.prototype = {
		add: function(kw) {
			this.keywords.push(kw);
		},
		matches: function(_re) {
			if (WIN.textMatch(this.nom, _re)) {return TRUE;}
			if (WIN.textMatch(this.pays, _re)) {return TRUE;}
			if (WIN.textMatch(this.code, _re)) {return TRUE;}
			var i = this.keywords.length;
			while (i) {
				--i;
				if (WIN.textMatch(this.keywords[i], _re)) {return TRUE;}
			}
			return FALSE;
		}
	};

	/**
	 * Objet qui référence toutes les intances de
	 * CompletionMEH présentes sur la page.
	 **/
	completionPool = (WIN.completionMEHPool = {
		/**
		 * Ajoute une complétion au pool.
		 *
		 * @param {!Object} comp complétion MEH à ajouter.
		 */
		add: function(comp) {
			poolArray.push(comp);
			return poolArray.length - 1;
		},
		/**
		 * Récupère une complétion dans le pool.
		 *
		 * @param {!number} index indice de la complétion MEH à récupérer.
		 */
		get: function(index) {
			return poolArray[index];
		}
	});

	var DEFAULT_MAX_TOWNS_IN_LIST = 6;
	/**
	 * @constructor
	 */
	WIN.CompletionMEH = function(elementText, elementData, positionDiv, maxTownsInList) {
		var theComp = this,
				poolIndex = (theComp.poolIndex = completionPool.add(theComp)),
				propositionsDiv;
		theComp.status = 'off';
		elementText.setAttribute('autocomplete', 'off');
		theComp.elementText = elementText;
		theComp.elementData = elementData;
		if (genericNavigator.navigator.id === MSIE) {
			addJavascriptToAttribute(elementText, 'onkeydown', 'completionMEHPool.get(' + poolIndex + ').toucheDown(event);');
			addJavascriptToAttribute(elementText, 'onkeyup', 'completionMEHPool.get(' + poolIndex + ').toucheUp(event);');
			addJavascriptToAttribute(elementText, 'onfocus', 'completionMEHPool.get(' + poolIndex + ').updatePropositions(event);');
			addJavascriptToAttribute(elementText, 'ondeactivate', 'completionMEHPool.get(' + poolIndex + ').delayedHidePropositions(500);');
		}
		else {
			addJavascriptToAttribute(elementText, 'onkeydown', 'return completionMEHPool.get(' + poolIndex + ').toucheDown(event);');
			addJavascriptToAttribute(elementText, 'onkeyup', 'return completionMEHPool.get(' + poolIndex + ').toucheUp(event);');
			addJavascriptToAttribute(elementText, 'onfocus', 'return completionMEHPool.get(' + poolIndex + ').updatePropositions(event);');
			addJavascriptToAttribute(elementText, 'onblur', 'completionMEHPool.get(' + poolIndex + ').delayedHidePropositions(500);');
		}
		propositionsDiv = DOC.createElement('DIV');
		propositionsDiv.style.visibility = 'hidden';
		propositionsDiv.className = 'completionMEH';
		if (genericNavigator.navigator.id === MSIE && genericNavigator.navigator.version <= 6.9) {
			propositionsDiv.style.width = WIN.MSIE6_LINE_WIDTH + 'px';
			propositionsDiv.style.padding = '5px';
		}
		positionDiv.appendChild(propositionsDiv);

		maxTownsInList = maxTownsInList || DEFAULT_MAX_TOWNS_IN_LIST;

		theComp.propositions = [];
		theComp.lineSelected = -1;
		theComp.lines = [];
		theComp.pageIndex = 0;
		theComp.updating = FALSE;

		theComp.toucheUp = function(event) {
			if (!event) {return FALSE;}
			if (WIN.shouldUpdatePropositions(event)) {
				theComp.updatePropositions(event);
			}
			return TRUE;
		};

		theComp.toucheDown = function(event) {
			if (!event) {return FALSE;}
			return WIN.completionToucheDown(this, event);
		};

		/**
		 * Crée un callback à exécuter après un download de complétion.
		 *
		 * @param {!string} prefix préfixe de ce qu'a tapé l'internaute.
		 * @return {Function} le callback créé.
		 */
		function createOnAfterUpdateHandler(prefix) {
			return function() {
				LOG.debug('completionMEH: /load_' + prefix + '.rjs reçu : ' + theComp.propositions.length + ' proposition(s)');
				// On signale la fin de mise à jour
				theComp.updating = FALSE;
			};
		}

		theComp.updatePropositions = function(event) {
			if (!event) {return FALSE;}
			if (theComp.updating) {return FALSE;}
			theComp.updating = TRUE;
			if (event.type !== 'focus') {
				elementData.value = '';
			}
			var elementTextValue = elementText.value;
			if (elementTextValue.length >= 3) {
				var prefix = WIN.getPrefix(elementTextValue);
				theComp.propositions = [];
				completionMEHRJS.invoke(completionMEHURLRoot + '/load_' + prefix + '.rjs', 'initMEHPropositions(' + poolIndex + ')', createOnAfterUpdateHandler(prefix));
			}
			else {
				theComp.hidePropositions();
				theComp.updating = FALSE;
			}
			return TRUE;
		};

		theComp.showPropositions = function() {
			// Si le div de positionnement des propositions n'est pas présent, inutile d'aller plus loin
			if (!propositionsDiv) {return;}

			if (elementText.$$evAutoFilled) {
				// Si l'élément texte a été pré-rempli automatiquement...
				// ... on supprime le flag d'information à ce sujet
				elementText.$$evAutoFilled = FALSE;
				// ... mais on n'affiche pas les propositions de suite
				return;
			}

			// On vide le div de positionnement de tous les éléments précédements affichés
			var node = propositionsDiv.lastChild;
			while (node) {
				propositionsDiv.removeChild(node);
				node = propositionsDiv.lastChild;
			}

			// On calcule l'expression régulière qui correspond au texte tapé par l'utilisateur
			var regExp = new RegExp('^' + WIN.formateText(elementText.value).replace(/\s+/, '\\s+') + '.*');

			// Cette variable va tenir le décompte des lignes des villes affichés
			var line = 0, i, reg, chaine, chaineSansAccent;
			theComp.lines = [];
			// On passe en revue toutes les propositions villes
			for (i = 0; i < theComp.propositions.length; i++) {
				// Si la proposition ville matche avec le champ texte
				if (theComp.propositions[i].matches(regExp)) {
					addJavascriptToAttribute(theComp.propositions[i].div, 'onmouseover', 'completionMEHPool.get(' + poolIndex + ').selectLine(' + line + ')');
					addJavascriptToAttribute(theComp.propositions[i].div, 'onmousedown', 'completionMEHPool.get(' + poolIndex + ').validLine(' + line + ')');
					theComp.lines[line] = theComp.propositions[i];
					// On insère la ville dans le tableau des lignes
					line++;

					// Initialisation des variables utilisé pour la mise en gras dans les proposition du texte saisie.
					reg = new RegExp('(' + WIN.formateText(elementText.value).replace(/\s+/, '\\s+') + ')', 'gi');
					chaine = theComp.propositions[i].div.childNodes[0].nodeValue;
					// Creation d'une chaine sans accent pour la mise en évidance.
					chaineSansAccent = WIN.replaceAccents(chaine);
					// Modification du DOM pour mettre en évidance la correspondance entre le texte fourni et celui proposé.
					theComp.propositions[i].div.childNodes[0].nodeValue = '';
					WIN.modifDomWhithSearch(chaine, chaineSansAccent, elementText.value, theComp.propositions[i].div, reg);
					propositionsDiv.appendChild(theComp.propositions[i].div);

					if (genericNavigator.navigator.id === MSIE && genericNavigator.navigator.version <= 6.9) {
						theComp.propositions[i].div.style.height = WIN.MSIE6_LINE_HEIGHT + 'px';
						theComp.propositions[i].div.style.width = WIN.MSIE6_LINE_WIDTH + 'px';
					}
				}
			}
			// Par défaut on n'a pas de ligne sélectionnée (-1), tout action sur les flêches du clavier va faire apparitre la selection grâce aux tests
			// su theComp.lineSelected dans les méthodes decreaseSelectedPosition() ou increaseSelectedPosition()
			theComp.hidePage();
			theComp.lineSelected = -1;
			theComp.pageIndex = 0;
			theComp.showPage();

			if (theComp.propositions.length > 0 && propositionsDiv && propositionsDiv.lastChild) {
				theComp.status = 'on';
				WIN.showPropositionsElement(propositionsDiv, line);
			}
			else {
				theComp.hidePropositions();
			}
		};

		theComp.hidePropositions = function() {
			theComp.status = 'off';
			WIN.hidePropositionsElement(propositionsDiv);
		};

		theComp.delayedHidePropositions = function(delay) {
			setTimeout('completionMEHPool.get(' + poolIndex + ').hidePropositions();', delay);
		};

		theComp.updatePage = function() {
			// On détermine l'éventuel nouveau pageIndex
			var newPageIndex = Math.floor(theComp.lineSelected / maxTownsInList);
			// S'il a changé on cache la page courante et on affiche la nouvelle
			if (theComp.pageIndex !== newPageIndex) {
				theComp.hidePage();
				theComp.pageIndex = newPageIndex;
				theComp.showPage();
			}
		};

		theComp.showPage = function() {
			var i;
			for (i = theComp.pageIndex * maxTownsInList; i < (theComp.pageIndex + 1) * maxTownsInList && i < theComp.lines.length && i >= 0; i++) {
				theComp.lines[i].div.style.display = 'block';
			}
		};

		theComp.hidePage = function() {
			var i;
			for (i = theComp.pageIndex * maxTownsInList; i < (theComp.pageIndex + 1) * maxTownsInList && i < theComp.lines.length && i >= 0; i++) {
				theComp.lines[i].div.style.display = 'none';
			}
		};

		theComp.decreaseSelectedProposition = function() {
			theComp.deselectProposition();
			theComp.lineSelected--;
			if (theComp.lineSelected < 0) {
				theComp.lineSelected = theComp.lines.length - 1;
			}
			theComp.selectProposition();
		};

		theComp.increaseSelectedProposition = function() {
			theComp.deselectProposition();
			theComp.lineSelected++;
			if (theComp.lineSelected >= theComp.lines.length) {
				if (theComp.lines.length > 0) {
					theComp.lineSelected = 0;
				}
				else {
					theComp.lineSelected = -1;
				}
			}
			theComp.selectProposition();
		};

		theComp.selectProposition = function() {
			if (theComp.lines[theComp.lineSelected]) {
				addClass(theComp.lines[theComp.lineSelected].div, 'selected');
			}
		};

		theComp.deselectProposition = function() {
			if (theComp.lines[theComp.lineSelected]) {
				removeClass(theComp.lines[theComp.lineSelected].div, 'selected');
			}
		};

		theComp.selectLine = function(line) {
			theComp.deselectProposition();
			theComp.lineSelected = line;
			if (theComp.lineSelected >= theComp.lines.length) {
				if (theComp.lines.length > 0) {
					theComp.lineSelected = 0;
				}
				else {
					theComp.lineSelected = -1;
				}
			}
			else if (theComp.lineSelected < 0) {
				theComp.lineSelected = theComp.lines.length - 1;
			}
			theComp.selectProposition();
		};

		theComp.validLine = function(line) {
			elementText.value = theComp.lines[line].nom;
			elementData.value = theComp.lines[line].data;
			// Par défaut, les villes ne sont pas visibles car il faut tester leur page d'appartenance
			theComp.hidePropositions();
		};
	}; // fin du constructeur CompletionMEH
}()); // Exécution ici

