

/**
 * 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,

			completionMECURLRoot,
			dn = EASY.path.cdn,
			completionMECRJS,
			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':
			completionMECURLRoot = dn + '/rjs/completion/MEC/es_ES';
			break;
		case 'it_IT':
			completionMECURLRoot = dn + '/rjs/completion/MEC/it_IT';
			break;
		case 'en_GB':
			completionMECURLRoot = dn + '/rjs/completion/MEC/en_GB';
			break;
		case 'de_DE':
			completionMECURLRoot = dn + '/rjs/completion/MEC/de_DE';
			break;
		//case 'fr_FR': // par défaut
		default:
			completionMECURLRoot = dn + '/rjs/completion/MEC/fr_FR';
			break;
	}

	completionMECRJS = new WIN.RemoteScript(completionMECURLRoot + '/load_default.rjs');

	/**
	 * Une propriété 'data' est créée à partir des infos disponibles :
	 *  - dans le meilleur des cas l'identifiant et l'alias de l'adresse sont insérés dedans (ex.: "l:4437|t:Aéroport Roissy - Charles De Gaulle")
	 *  - si l'identifiant de l'adresse manque, on utilise le texte (alias de l'adresse)
	 * REMARQUE : on part du principe de l'alias de l'adresse existe toujours
	 *
	 * @constructor
	 */
	WIN.PropositionMECAdresse = function(alias, ville, pays, id) {
		var thisPropAdd = this;
		thisPropAdd.alias = alias;
		thisPropAdd.ville = ville;
		thisPropAdd.pays = pays;
		thisPropAdd.id = id;
		if (id) {
			thisPropAdd.data = 'l:' + id + '|t:' + alias;
		}
		else {
			thisPropAdd.data = alias;
		}
		thisPropAdd.div = DOC.createElement('DIV');
		thisPropAdd.div.className = 'propositionAdresse';
		thisPropAdd.div.appendChild(DOC.createTextNode(alias + ', ' + ville + ', ' + pays));
		thisPropAdd.div.style.display = 'none';
		thisPropAdd.index = -1;
		thisPropAdd.keywords = [];
	};
	WIN.PropositionMECAdresse.prototype = {
		add: function(kw) {
			this.keywords.push(kw);
		},
		matches: function(_re) {
			if (WIN.textMatch(this.alias, _re)) {return TRUE;}
			if (WIN.textMatch(this.ville, _re)) {return TRUE;}
			if (WIN.textMatch(this.pays, _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
	 * CompletionMEC présentes sur la page.
	 **/
	completionPool = (WIN.completionMECPool = {
		/**
		 * Ajoute une complétion au pool.
		 *
		 * @param {!Object} comp complétion MEC à 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 MEC à récupérer.
		 */
		get: function(index) {
			return poolArray[index];
		}
	});

	var DEFAULT_MAX_ADDRESSES_IN_LIST = 6;
	/**
	 * @constructor
	 */
	WIN.CompletionMEC = function(elementText, elementData, positionDiv, maxAddressesInList) {
		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', 'completionMECPool.get(' + poolIndex + ').toucheDown(event);');
			addJavascriptToAttribute(elementText, 'onkeyup', 'completionMECPool.get(' + poolIndex + ').toucheUp(event);');
			addJavascriptToAttribute(elementText, 'onfocus', 'completionMECPool.get(' + poolIndex + ').updatePropositions(event);');
			addJavascriptToAttribute(elementText, 'ondeactivate', 'completionMECPool.get(' + poolIndex + ').delayedHidePropositions(500);');
		}
		else {
			addJavascriptToAttribute(elementText, 'onkeydown', 'return completionMECPool.get(' + poolIndex + ').toucheDown(event);');
			addJavascriptToAttribute(elementText, 'onkeyup', 'return completionMECPool.get(' + poolIndex + ').toucheUp(event);');
			addJavascriptToAttribute(elementText, 'onfocus', 'return completionMECPool.get(' + poolIndex + ').updatePropositions(event);');
			addJavascriptToAttribute(elementText, 'onblur', 'completionMECPool.get(' + poolIndex + ').delayedHidePropositions(500);');
		}
		propositionsDiv = DOC.createElement('DIV');
		propositionsDiv.style.visibility = 'hidden';
		propositionsDiv.className = 'completionMEC';
		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);

		maxAddressesInList = maxAddressesInList || DEFAULT_MAX_ADDRESSES_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('completionMEC: /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 = [];
				completionMECRJS.invoke(completionMECURLRoot + '/load_' + prefix + '.rjs', 'initMECPropositions(' + 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 addresses affichées
			var line = 0, i, reg, chaine, chaineSansAccent;
			theComp.lines = [];
			// On passe en revue toutes les propositions adresses
			for (i = 0; i < theComp.propositions.length; i++) {
				// Si la proposition adresses matche avec le champ texte
				if (theComp.propositions[i].matches(regExp)) {
					addJavascriptToAttribute(theComp.propositions[i].div, 'onmouseover', 'completionMECPool.get(' + poolIndex + ').selectLine(' + line + ')');
					addJavascriptToAttribute(theComp.propositions[i].div, 'onmousedown', 'completionMECPool.get(' + poolIndex + ').validLine(' + line + ')');
					theComp.lines[line] = theComp.propositions[i];
					// On insère l'adresse 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
			// sur 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('completionMECPool.get(' + poolIndex + ').hidePropositions();', delay);
		};

		theComp.updatePage = function() {
			// On détermine l'éventuel nouveau pageIndex
			var newPageIndex = Math.floor(theComp.lineSelected / maxAddressesInList);
			// 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 * maxAddressesInList; i < (theComp.pageIndex + 1) * maxAddressesInList && i < theComp.lines.length && i >= 0; i++) {
				theComp.lines[i].div.style.display = 'block';
			}
		};

		theComp.hidePage = function() {
			var i;
			for (i = theComp.pageIndex * maxAddressesInList; i < (theComp.pageIndex + 1) * maxAddressesInList && 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].ville + ' [' + theComp.lines[line].alias + ']';
			elementData.value = theComp.lines[line].data;
			// Par défaut, les adresses ne sont pas visibles car il faut tester leur page d'appartenance
			theComp.hidePropositions();
		};
	}; // fin du constructeur CompletionMEC
}()); // Exécution ici


