//Copyright (C) 2003-2011 AJLSM, Anaphore
//Voir le fichier LICENCE
//$Id: SearchFormSuggest.js 21168 2011-11-28 13:22:05Z pdechando $

/**
 * @fileOverview Classe permettant d'initialiser les suggetions pour le formulaire de recherche avancé 
 * @author Julien Huet
 */
/**
 * @class Classe permettant d'initialiser les suggetions pour le formulaire de recherche avancé 
 * @author Julien Huet
 */
var SearchFormSuggest = new Class(/** @lends SearchFormSuggest */{

	/**
	* <strong>Constructor</strong><br/> 
	* @param {SearchForm} searchForm
	*/
	initialize: function(searchForm){
		/*  La liste des critères de type "suggest" dans un tableau de String  */
		this.suggests = new Array();
		this.simpleSuggest = new Array();
		this.isSuggests = false;
		this.searchForm = searchForm;
	},

	/***
	* Initialisation des suggestions pour le formulaire de recherche avancé
	*/
	initSimpleSuggests: function(){
		var mid;
		$$('input.pl-simple-suggest').each( function(o){
			mid = o.name;
			if ( mid!=null ) {
				if ( !mid.blank() ) {
					this.simpleSuggest.push( mid );
				}
			}
		}.bind(this));
		if( this.simpleSuggest==null || this.simpleSuggest.length==0 ) {
			return;
		}

		$A(this.simpleSuggest).clean().each( function(o,i){
			this.initSuggest( o, i, 'simple' );
			this.isSuggests = true;
		}.bind(this));
	},
	
	/**
	* Initialisation des suggestions pour le formulaire de recherche avancé
	*/
	initSuggests: function() {
		var mid;
		$$('input.pl-suggest').each( function(o){
			mid = o.name;
			if ( mid!=null ) {
				if ( !mid.blank() ) {
					this.suggests.push( mid );
				}
			}
		}.bind(this));
		if( this.suggests==null || this.suggests.length==0 ) {
			return;
		}
		$A(this.suggests).clean().each( function(o,i){
			this.initSuggest( o, i, 'multiple');
			this.isSuggests = true;
		}.bind(this));
	},

	/**
	* Fonction interne pour créer une suggestion YUI
	* @private
	* @param {Object} o
	* @param {Object} i
	* @param {String} mode
	*/
	initSuggest: function(o, i, mode){
		var dsXhr = new YAHOO.widget.DS_XHR( 'functions/suggest.json', ['results', 'text', 'option', 'freq'] );
		dsXhr.scriptQueryParam = 'value';
		dsXhr.connMethodPost = true; //false par défaut... mais IE n'aime pas les accents en GET !
		/*  INFO:	Boucler sur les critères de type "suggest" et initialiser
			leur auto-complete. On reconnaît un tel critère à ses
			composants :
			1) input/@id='query[0-9]+_input'	: zone de saisie
			2) input/@id='query[0-9]+_field'	: nom du champ
			3)   div/@id='query[0-9]+_container'	: conteneur suggestions
			4)   div/@id='query[0-9]+_values'	: valeurs sélectionnées
		[MP]  */
		var idi = o + '-input',
		    idf = o + '-field',
		    idc = o + '-container',
		    idv = o + '-values';
		if( $(idi)==null
			|| $(idf)==null
			|| $(idc)==null
			|| $(idv)==null
		) {
			/*  On supprime le critère qui n'est pas complet de la liste ; ça permet de ne pas s'embêter lors de la validation, cf. suggest2work() [MP]  */
			this.suggests.splice(1,1);
			return;
		}
		var sdxdbid = '';
		try{ sdxdbid = dbid; } catch(e){}
		
		// Construction du filtre si besoin
		var _fo  = $$( '.pl-fo-' + o )[0]; // l'opérateur
		var _ffs = $$( '.pl-ff-' + o ), // la liste des champs du filtre
		    _fvs = $$( '.pl-fv-' + o ); // la liste des valeurs du filtre
		var _filters = "";
		if ( _ffs != null && _ffs.length != 0 ) {
      _ffs.each( function(_ff, _rank) {
        if (_ff != null && _ff.value != null && _ff.value != "") 
        {
          _fv = _fvs[_rank];
          if (_fv != null && _fv.value != "") {
            _filters += "&ff=" + _ff.value + "&fv=" + _fv.value;
          }
        }
      });
      if (_fo != null && _fo.value != null && _fo.value != "") {
        _filters += "&fo=" + _fo.value;
      }
		}
		_fo = null; _ffs = null; _fvs = null;

		// Définition de la partie "racines" de la requête (ie, la partie à laquelle on ajoutera la valeurs saisie par l'utilisateur (dsXhr.scriptQueryParam définie plus haut).
		dsXhr.scriptQueryAppend = ( (sdxdbid != '')? 'base=' + dbid.split(' ').join('&base=') : '' ) + // l'identifiant de(s) base(s) de documents ; la variable est initialisee dans search.xsl au moment de la construction de la base XHTML
                              '&field=' + $(idf).value + _filters; // TODO (MP) : les paramètres qu'il fau pour les filtres à mettre ici. 
    var autoComp = new YAHOO.widget.AutoComplete(idi,idc, dsXhr);
		/*  Modifier le delai d'activation du suggest. 0.2'' par défaut.  */
		autoComp.queryDelay = 0.5; /* TODO: Attendre que l'utilisateur ait fini de taper plutot que d'attendre 0.5'' apres que l'utilisateur ait tape la premiere lettre [MP]  */
		autoComp.prehighlightClassName = 'yui-ac-prehighlight';
		autoComp.useShadow = true;
		autoComp.forceSelection = true;
		autoComp.maxResultsDisplayed = 10;
		autoComp.useIFrame = true; // NOTE (MP) : Permet aux suggests d'etre correctement affiches dans IE s'ils sont places au-dessus d'une liste (select). Comportement bizarre avec Opera qui rend pas le service inutilisable pour autant : affichage d'un "gros bloc blanc".
		autoComp.animHoriz = true;
		autoComp.minQueryLength = 1;
		/* On surcharge complètement cette méthode */
		autoComp.generateRequest  = function(sQuery)
		{
			/* Code récupéré depuis YUI 2.6 */
			var dataType = this.dataSource.dataType;
			// Transform query string in to a request for remote data
			// By default, local data doesn't need a transformation, just passes along the query as is.
			if(dataType === YAHOO.util.DataSourceBase.TYPE_XHR) {
				// By default, XHR GET requests look like "{scriptURI}?{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
				if ( !this.dataSource.connMethodPost ) {
					sQuery = searchForm.suggest.parseSuggestQuery(sQuery);
					/* Fin surcharge */
					sQuery = (this.queryQuestionMark ? '?' : '') + (this.dataSource.scriptQueryParam || 'query') + '=' + sQuery + (this.dataSource.scriptQueryAppend ? ('&' + this.dataSource.scriptQueryAppend) : '');
				}
				// By default, XHR POST bodies are sent to the {scriptURI} like "{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
				else {
					sQuery = (this.dataSource.scriptQueryParam || 'query') + '=' + sQuery + (this.dataSource.scriptQueryAppend ? ('&' + this.dataSource.scriptQueryAppend) : '');
				}
			}
			// By default, remote script node requests look like "{scriptURI}&{scriptCallbackParam}={callbackString}&{scriptQueryParam}={sQuery}&{scriptQueryAppend}"
			else if(dataType === YAHOO.util.DataSourceBase.TYPE_SCRIPTNODE) {
				sQuery = '&' + (this.dataSource.scriptQueryParam || 'query') + '=' + sQuery + (this.dataSource.scriptQueryAppend ? ('&' + this.dataSource.scriptQueryAppend) : '');
			}
			
			// On va ajouter le filtre sur les entrées du cadre de classement
			return sQuery += searchForm.suggest.getCdcFilterParams();
			// return sQuery;
		};

		autoComp.textboxFocusEvent.subscribe(function(){
			var sInputValue = $(idi).value;
			if ( sInputValue.length === 0 ) {
				var oSelf = this;
				setTimeout(function(){oSelf.sendQuery(sInputValue);}, 0);
			}
		});
		
		/* Pour vider la zone de saisie si il n'y a aucun résultat */
		autoComp.dataErrorEvent.subscribe(function(event, obj)
		{
			// Vide le "input" pour éviter que la recherche soit validée avec des valeurs ne donnant aucun résultat
			$(idi).value = '';
		}.bind(this));
		
		
		/* Pour agir sur le conteneur de resultats, par exemple le placer correctement ou le redimensionner. */
		autoComp.doBeforeExpandContainer = function(oTextbox, oContainer, sQuery, aResults){
			return this.doBeforeExpandContainer(oTextbox, oContainer, sQuery, aResults,autoComp);
		}.bind(this);
		
		/* Pour formater les resultats ici : texte (docFreq)
		autoComp.formatResult = function(oResultItem, sQuery) {
		return oResultItem[0] + " (" + oResultItem[2] + ")";
		}; */
		
		/* Pour s'assurer que la zone de saisie est vidée dès que la liste auto-suggestion disparaît */
		autoComp.containerCollapseEvent.subscribe(function(event, obj) {
			$(idi).value = '';
		}.bind(this));

		autoComp.itemSelectEvent.subscribe(function(event, obj) {
			var value = obj[2][0];	// l'objet est un resultat format JSON suivant le schema definit plus haut
			if ( mode != 'simple' ) {
				this.searchForm.addOccurrence($(idv), value);
				$(idi).value = '';
			}
		}.bind(this));
	},
	
	/**
	* Modifie la requête pour ajouter les entrées du cadre de classement qui 
	* ont été cochées.
	*/
	getCdcFilterParams: function() {
		var _query = "";
		try
		{
			if (this.searchForm != null && this.searchForm.cdcSearch != null && this.searchForm.cdcSearch != '') {
				var _ids = this.searchForm.cdcSearch.getCdcIdsChecked(); // Récupérer les ID des entrées du cadre de classement
				if (_ids != null) { // Les ajouter comme filtre pour le suggest
					_ids.each(function(o){
	//					Fix bug : ne fonctionne plus suite à migration en Pleade 3.4
	//					if ( o.getValue() != null ) {
	//						_query += '&ff=cdcall&fv=' + o.getValue();
	//					}
						// ID of the selected IR int CdC
						var _id = o["data"]["id"];
						if ( _id != null ) {
							_query += '&ff=cdcall&fv=' + _id;
						}
					});
				}
				_ids = null;
			}
		} catch(e){ /* Catch une exception au cas où on n'aurait pas de cdcSearch, comme ça on continue le traitement */ }
		return _query;
	},

	/**
	* Fonction appellée pour parser les caractères entrés
	* @param (String) sQuery Requete a parser
	*/
	parseSuggestQuery : function(sQuery){
		/* Début surcharge */
		var nQuery = sQuery;
		/* TODO: HACK pour creer une WilcardTermEnum avec * au debut et a la fin
		// troncature au debut et a la fin
		if( sQuery.match(/^\*.+\*$/) ){;}
		else{
			// pas de troncature au debut
			if( !sQuery.match(/^\*.+$/) )
					nQuery = '*' + nQuery;
			// pas de troncature a la fin
			if( !sQuery.match(/^.+\*$/) )
					nQuery = nQuery + '*';
		}
		*/

    // echappe les caracteres reserves en expression reguliere dans la requete utilisateur.
    nQuery = nQuery.replace(/(%28|%29|%2E|%5B|%5C|%5D%|5E|%7B|%7C|%7D|%3F)/g, "\\$1");

    if( suggest_starts_with=='true'
       && !sQuery.match(/^\*.+$/) ) {
      nQuery = '^' + nQuery;
    }

		return nQuery;
		/* Fin surcharge */
	},

	/**
	* Surcharge de la methode YUI
	* @param {Element} oTextbox
	* @param {Element} oContainer
	* @param {String} sQuery
	* @param {Array} aResults
	* @param {Boolean} autoComp
	*/
	doBeforeExpandContainer : function(oTextbox, oContainer, sQuery, aResults,autoComp) {
		var pos = YAHOO.util.Dom.getXY(oTextbox);
		pos[1] += YAHOO.util.Dom.get(oTextbox).offsetHeight + 2;
		/* Les positions pour la solution temporaire de la liste à droite
		pour parer au bogue IE
		pos[1] += YAHOO.util.Dom.get(oTextbox).offsetHeight - 17;
		pos[0] += YAHOO.util.Dom.get(oTextbox).offsetWidth + 5; */
		// DEBUG: IE a besoin de ce z-index pour afficher la liste des suggests au-dessus des boutons de validation du formulaire
		YAHOO.util.Dom.setStyle(oContainer, 'z-index', '1000');
		YAHOO.util.Dom.setXY(oContainer,pos);
		// on ajoute une classe css odd/even sur les li
		var lis = autoComp.getListItems();
		if( lis!=null && lis.length > 0 ) {
			var li = null;
			for ( var i = 0, l = lis.length ; i < l ; i++ ) {
				li = lis[i];
				if ( li != null ) {
					YAHOO.util.Dom.addClass(li, ((i % 2 == 0) ? 'odd' : 'even') );
				}
			}
      if (aResults.length > autoComp.maxResultsDisplayed ) {
        this.footer = _usersMessages.search_form_msg_suggest_more;
        autoComp.setFooter(this.footer);
      }
      else {autoComp.setFooter();}
			li=null;
		}
		lis=null;
		return true;
	},

	/***
	* Fonction pour l'initialisation des list combo a plusieurs entrée (type suggest)
	*/
	initMultipleComboSelect: function(){
		$$('select.pl-form-slct-multiple-combo').each(function(_select){
			var n = _select.name.replace(/\query/g, '');
			/* [JC] Le code ci-dessous recopie les valeurs, et à tendance à dupliquer le boulot déjà fait par la XSL */
			/*_select.select('option[selected="selected"]').each(function(opt){
				var el = $('query'+n+'-values');
				var value = opt.value;
				var valueUI = opt.innerHTML;
				if(el!=null && !value.blank()){
				// TODO: i18n
				var opdisplay = false;
				if(_select.hasClass('dyn_display_op_multiple_combo'))
					opdisplay = true;
				var update_display_op_multiple_combo_string = "";
				if(opdisplay)
						update_display_op_multiple_combo_string = "update_display_op_multiple_combo('" + n + "')";
				el.update(el.innerHTML + '<div class="pl-form-suggest-value"><a href="#" onclick="javascript:this.parentNode.dispose();'+ update_display_op_multiple_combo_string +'" title="'+ _usersMessages.search_form_list_item_selected_remove +'"><span class="real-value access">' + value + '</span>' + valueUI + '</a></div>');
				if(opdisplay)
					update_display_op_multiple_combo(n);
				}
			});*/
			_select.addEvent('change', function(){this.searchForm.addOccurrenceFromCombo(n, _select)}.bind(this) );
		});
	}
});

