/**
* Fonctions générales utilisées par toutes les versions de completion (MEV, MEH...)
**/

var ST=/^sai(|n|nt(e?))/, SAINT=/^st/, SAINTE=/^ste/, REP=/rep\.?/;
var REG_SAINT=new RegExp("(sai(|n|nt(e?)))", "gi"), REG_ST=new RegExp("(st )", "gi"), REG_STE=new RegExp("(ste )", "gi");
/**
* Cette fonction utilisée par les matching, teste si le texte correspond à l'expression régulière. Cette opération utilise pour text les règles de 
* formatage définies par la fonction formateText.
* - text: le texte à matcher
* - regExp: l'expression régulière à tester
* Retourne un booléen.
**/
function textMatch(text, regExp){
	text=formateText(text);
	if(ST.test(text)){
		if(text.replace(ST, "st"+RegExp.$2).match(regExp)){return true;}
	}
	if(SAINT.test(text)){
		if(text.replace(SAINT, "saint"+RegExp.$2).match(regExp)){return true;}
	}
	if(SAINTE.test(text)){
		if(text.replace(SAINT, "sainte"+RegExp.$2).match(regExp)){return true;}
	}
	if(REP.test(text)){
		if(text.replace(REP, "republique").match(regExp)){return true;}
		if(text.replace(REP, "republic").match(regExp)){return true;}
		if(text.replace(REP, "republica").match(regExp)){return true;}
		if(text.replace(REP, "republik").match(regExp)){return true;}
	}
	return text.match(regExp);
}

/**
 * Cette fonction permet l'extraction du prefixe (3 premiers caractères) d'une chaine après formatage.
 */
function getPrefix(text) {
	text=formateText(text);
	if(text.length<3){return null;}
	text=text.substring(0,3);
	return text;
}

/**
* Le formatage consiste à:
* - convertir en low case
* - supprimer toute l'accentuation
* ATTENTION: Ce formatage est normalisé, IL NE DOIT PAS ETRE MODIFIE
**/
function replaceAccents(text) {
	text=text.toLowerCase();
	text=text.replace(/à/g,"a");
	text=text.replace(/â/g,"a");
	text=text.replace(/ä/g,"a");
	text=text.replace(/å/g,"a");
	text=text.replace(/ã/g,"a");
	text=text.replace(/á/g,"a");
	text=text.replace(/é/g,"e");
	text=text.replace(/ê/g,"e");
	text=text.replace(/è/g,"e");
	text=text.replace(/ë/g,"e");
	text=text.replace(/ï/g,"i");
	text=text.replace(/î/g,"i");
	text=text.replace(/í/g,"i");
	text=text.replace(/ì/g,"i");
	text=text.replace(/ö/g,"o");
	text=text.replace(/ô/g,"o");
	text=text.replace(/ò/g,"o");
	text=text.replace(/ø/g,"o");
	text=text.replace(/ó/g,"o");
	text=text.replace(/ù/g,"u");
	text=text.replace(/û/g,"u");
	text=text.replace(/ü/g,"u");
	text=text.replace(/ç/g,"c");
	text=text.replace(/ñ/g,"n");
	return text;
}

/**
* Le formatage consiste à:
* - convertir en low case
* - supprimer toute l'accentuation et typographie particulière
* - remplacer tous les signes autres que a-z 0-9 et le signe espace en espaces
* - compacter les séquences d'espaces en un seul
* - trimer
* ATTENTION: Ce formatage est normalisé, IL NE DOIT PAS ETRE MODIFIE
**/
function formateText(text) {
	text=replaceAccents(text);
	text=text.replace(/[^a-z0-9 ]/g," ");
	text=text.replace(/\s\s+/g," ");
	text=text.replace(/^\s+/,"");
//	text=text.replace(/\s+$/,"");
	return text;
}

/**
 * Selon la touche ayant généré l'evenement 'event' donné,
 * on retourne vrai ou faux pour dire s'il est nécessaire de
 * mettre à jour une liste de propositions.
 */
function shouldUpdatePropositions(event){
	// Esquive de quelques touches...
	switch(event.keyCode){
		case 9: // TAB
		case 13:// ENTER
		case 16:// SHIFT
		case 17:// CONTROL
		case 18:// ALT
		case 27:// ECHAP
		//case 32:// ESPACE
		case 37:// GAUCHE
		case 39:// DROITE
		case 38:// HAUT
		case 40:// BAS
			return false;
	}
	// Pour toute autre touche on met à jour la liste de propositions
	return true;
}

/**
 * Cette méthode permet de centraliser le fonctionnement des touches du clavier sur les completions ME.
 * Elle gère l'évènement 'onkeyup' des champs INPUT TEXT sur lesquels la completion est activée.
 * La valeur de retour permet de préciser si l'on doit laisser remonter l'évenement au niveau du navigateur (oui : true ; non : false)
 * Pour IE le système est différent et on doit modifier l'évènement lorsque celui-ci doit être bloqué (car il ne gère pas et n'accepte pas la valeur de retour)
 */
function completionToucheDown(completion, event){
	var blockEvent=false;

	if(completion.status==="off"){
		// Si la complétion est inactive on remonte l'événement au navigateur sauf si la touche du bas est enfoncee.
		if(event.keyCode==40){
			completion.updatePropositions(event);
			blockEvent=true;
		}
	}
	else switch(event.keyCode){
		case 38:// HAUT
			completion.decreaseSelectedProposition();
			completion.updatePage();
			blockEvent=true;
			break;
		case 40:// BAS
			completion.increaseSelectedProposition();
			completion.updatePage();
			blockEvent=true;
			break;

		case 13:// validation par ENTER
		case 9:// validation par TAB
			if(completion.lineSelected>=0&&completion.lineSelected<completion.lines.length){
				// En fait, hors bug, la seule valeur possible hors ces bornes est -1 qui est la valeur par défaut qui correspond au fait que l'utilisateur
				// n'a pas touché les flêches du clavier
				completion.validLine(completion.lineSelected);
				// on ne laisse remonter l'événement au navigateur que si la ligne est validée avec TAB
				blockEvent=event.keyCode==13;
			}
			else{
				// Dans l'autre cas, aucune sélection n'a été faite dans la ligne, et on ne doit tenir compte que de ce qui a été tapé dans le champ texte
				completion.hidePropositions();
				// On ne peut pas vider le champ (comme ligne en commentaire) dans ce cas là (on risque de supprimer une donnée insérée par la completion lors d'un choix précédent).
				// A la place, cela est effectué lors de l'insertion d'un caractère ('updatePropositions()').
				//completion.elementData.value="";
				// Et on remonte biensûr l'événement (comme si la completion n'existait pas)
			}
			break;
		case 27:// ECHAP : masquage des propositions
			completion.hidePropositions();
			blockEvent=true;
			break;
	}

	// Toute autre touche : on ne fait rien on transmet l'événement au navigateur et on attends l'événement 'onkeyup' pour mettre à jour les propositions [cf. completion.toucheUp()]

	// Traitement spécifique pour le blocage de l'évènement sur IE
	if(blockEvent&&genericNavigator.navigator.id==MSIE){
		event.cancelBubble=true;
		event.returnValue=false;
	} 

	return !blockEvent;
}

/**
 * Permet d'afficher l'element de propositions s'il existe (quelque soit le navigateur)
 */
function showPropositionsElement(element, nb_lines){
	if(!element){return;}
	element.style.visibility="visible";
	if(genericNavigator.navigator.id==MSIE&&genericNavigator.navigator.version<=6.9) {
		var iframe=document.createElement("IFRAME");
		iframe.style.display="none";
		iframe.style.display="block";
		iframe.style.position="absolute";
		iframe.style.top="0";
		iframe.style.left="0";
		iframe.style.zIndex="-1";
		iframe.style.filter="mask()";
		iframe.style.width=(MSIE6_LINE_WIDTH+10)+"px";
		iframe.style.height=(MSIE6_LINE_HEIGHT*nb_lines+10)+"px";
		iframe.style.background="none";
		iframe.frameBorder=0;
		iframe.scrolling="no";
		element.appendChild(iframe);
	}
}

/**
 * Permet de masquer l'element de propositions s'il existe (quelque soit le navigateur)
 */
function hidePropositionsElement(element){
	if(!element){return;}
// NB : on fait pas ça, cela empeche le champ de reprendre le focus sur IE
// NB2: ça sera fait avant l'affichage suivant de la complétion si besoin
//	var node=element.lastChild;
//	while(node){
//		element.removeChild(node);
//		node=element.lastChild;
//	}
	element.style.visibility="hidden";
}

/**
* Cette méthode permet l'ajout du synonyme dans la proposition si la difference entre les sommes des codes de caractères du synomyme et du nom est supérieure à 75%.
* L'ajout n'est effectué que si la chaine sans accent ne contient pas la saisie de l'utilisateur et les differentes expressions régulières pour les "saint(e)".
* @param propositions : proposition à affiché.
* @param chaine : chaine de caractères affiché.
* @param chaineSansAccent : chaine de caractères affiché sans les accents.
* @param regExp : expression régulière qui commence par la chaine de caractères rentré par l'utilisateur.
* @param reg : expression régulière, insensible à la case, de la chaine de caractères rentré par l'utilisateur.
**/
function ajoutSynonyme(proposition, chaine, chaineSansAccent, regExp, reg){
	if(!chaineSansAccent.match(reg) && !chaineSansAccent.match(REG_SAINT) && !chaineSansAccent.match(REG_ST) && !chaineSansAccent.match(REG_STE)){
		var syn = proposition.retournMatch(regExp);
		if(syn!=null){
			var entierNom=0;
			for (var f=0; f<proposition.nom.length; f++) {
				   entierNom=entierNom+proposition.nom.charCodeAt(f);
			}
			var entierSyn=0;
			for (var f=0; f<syn.length; f++) {
				entierSyn=entierSyn+syn.charCodeAt(f);
			}
			var entier=0;
			if(entierNom<entierSyn) entier=entierNom/entierSyn;
			if(entierSyn<entierNom) entier=entierSyn/entierNom;
			if(entier<0.75){
				chaine = proposition.nom+" ["+syn+"], "+proposition.pays;
			}
		}
	}
	return chaine;
}

/**
* Modification du DOM contenant la proposition pour mettre en évidance le corespondance avec le texte saisie.
* @param chaine : chaine de caractères affiché.
* @param chaineSansAccent : chaine de caractères affiché sans les accents.
* @param elementTextValue : chaine de caractères saisie par l'utilisateur.
* @param propositionDiv : div contenant la proposition affiché.
* @param reg : expression régulière, insensible à la case, de la chaine de caractères rentré par l'utilisateur.
**/
function modifDomWhithSearch(chaine, chaineSansAccent, elementTextValue, propositionDiv, reg){
	// Suppression des tirets dans la chaine sans les accents et du texte saisie pour simplifier la correspondance.
	elementTextValue=elementTextValue.replace(/-/g," ");
	chaineSansAccent=chaineSansAccent.replace(/-/g," ");

	// Suppression des espaces multiples dans le texte saisie.
	elementTextValue=elementTextValue.replace(/\s\s+/g," ");
	
	var positionChar = new Array();
	// Initilisation du tableau qui permet de savoir si un caractère doit être mis en évidence.
	for (var f=0; f<chaineSansAccent.length; f++) {
		positionChar[f] = false;
	}
	// Recherche des caractères qui doivent être mis en évidence par rapport au texte saisie par l'utilisateur.
	if(chaineSansAccent.match(reg)){
		var quantiteDiese = 0;
		chaineSansAccent = chaineSansAccent.replace(reg, "#$1");
		
		for (var f=0; f<chaineSansAccent.length; f++) {
			if(chaineSansAccent.charAt(f)=="#"){
				positionChar[f-quantiteDiese] = true;
				quantiteDiese++;
			}
		}
	}
	// Recherche des caractères qui doivent être mis en évidence par rapport au texte saisie par l'utilisateur si il est de type "saint(e)".
	if(elementTextValue.match(REG_SAINT) || elementTextValue.match(REG_ST) || elementTextValue.match(REG_STE)){
		if(chaine.match(REG_ST)){
			var quantiteDiese = 0;
			chaineSansAccent = chaine.replace(REG_ST, "#$1");
			for (var f=0; f<chaineSansAccent.length; f++) {
				if(chaineSansAccent.charAt(f)=="#"){
					positionChar[f-quantiteDiese] = true;
					quantiteDiese++;
				}
			}
		}
		if(chaine.match(REG_STE)){
			var quantiteDiese = 0;
			chaineSansAccent = chaine.replace(REG_STE, "#$1");
			for (var f=0; f<chaineSansAccent.length; f++) {
				if(chaineSansAccent.charAt(f)=="#"){
					positionChar[f-quantiteDiese] = true;
					quantiteDiese++;
				}
			}
		}
	}
	var div = document.createElement("div");
	div.appendChild(document.createTextNode(""));
	// Modification du DOM en fonction des caractères à mettre en évidence.
	var txt="";
	for (var f=0; f<chaine.length; f++) {
		if(positionChar[f]){
			if(f!=0) propositionDiv.appendChild(document.createTextNode(txt));
			// Modification de la longuer du texte à mettre en evidence pour les recherche de type "saint(e)".
			var nbCaracSaisie=elementTextValue.replace(/^\s+/g,'').length;
			txt=chaine.substr(f, nbCaracSaisie);
			if(elementTextValue.match(REG_SAINT) && txt.match(REG_ST)) {
				if(nbCaracSaisie==4) nbCaracSaisie=nbCaracSaisie-2;
				if(nbCaracSaisie>4) nbCaracSaisie=nbCaracSaisie-3;
			}
			if(elementTextValue.match(REG_SAINT) && txt.match(REG_STE)) {
				if(nbCaracSaisie==4) nbCaracSaisie=nbCaracSaisie-1;
				if(nbCaracSaisie>4 && nbCaracSaisie<7) nbCaracSaisie=nbCaracSaisie-2;
				if(nbCaracSaisie>6) nbCaracSaisie=nbCaracSaisie-3;
			}
			// Création d'un node pour la mise en évidence dans les propositions.
			txt=chaine.substr(f, nbCaracSaisie);
			var bold = document.createElement("b");
			bold.appendChild(document.createTextNode(txt));
			propositionDiv.appendChild(bold);
			f=f+nbCaracSaisie-1;
			txt="";
		}else{
			txt+=chaine.charAt(f);
		}
	}
	propositionDiv.appendChild(document.createTextNode(txt));
}
