
TextSuggest = Class.create();

TextSuggest.prototype = {
	
   initialize: function(anId, url, options, related, related2) {
      this.id          = anId;
	  this.relatedField = related;
	  this.relatedField2 = related2;
      var browser = navigator.userAgent.toLowerCase();
      this.isIE        = browser.indexOf("msie") != -1;
      this.isOpera     = browser.indexOf("opera")!= -1;
      this.textInput   = $(this.id);
      this.suggestions = [];
      this.setOptions(options);
      this.initAjax(url);
      this.injectSuggestBehavior();
	  this.iFrame	   =null;
	  this.height		= 0;
	  this.spanded		= false;
	  this.use_css= false;
	  this.use_layers=false;
	  this.use_gebi=false;
	  
	  
	 if (document.getElementById) { 
		this.use_gebi = true; 
	 } 
	 else if (document.all) { 
		this.use_css=true; 
	 }
	 else if (document.layers) { 
		this.use_layers=true; 
	 }
	  
//	  this.onChangeValue	= onChangeValue;
	  document.onclick       = this.DocClickHandler.bindAsEventListener(this);
   },
	onChangeValue: function(){
		//empty
		 window.status="changed"
   },
	DocClickHandler: function(e){
		var src = e.srcElement ? e.srcElement : e.target;
		var sId="";
		try{
				sId= src.id;
				if(sId.indexOf(this.id)<0)
						this.hideSuggestions();
		}catch(e){}
		
   },
   initAjax: function(url) {
      ajaxEngine.registerRequest( this.id + '_request', url );
      ajaxEngine.registerAjaxObject( this.id + '_updater', this );
   },
	getText: function(){
	   return this.textInput.value;
   },
	getValue:function(){
	   return $( this.id + "_hidden" ).value;
   },
    setText: function(value){
	   this.textInput.value = value;
   },
	setValue:function(value){
	   $( this.id + "_hidden" ).value = value;
   },
   clear: function(){
	   this.textInput.value="";
	   $( this.id + "_hidden" ).value="";
	   this.onChangeValue(this);
	},

   setOptions: function(options) {
      this.options = {
         suggestDivClassName: 'suggestDiv',
         suggestionClassName: 'suggestion',
         matchClassName     : 'match',
         matchTextWidth     : true,
         selectionColor     : '#D6F2F8',
         matchAnywhere      : true,
         ignoreCase         : true,
		 ieHeight			: 15		
         
      }.extend(options || {});
   },
      
   injectSuggestBehavior: function() {
      if ( this.isIE )
         this.textInput.autocomplete = "off";
      var keyEventHandler = new TextSuggestKeyHandler(this);
      new Insertion.After( this.textInput,
                           '<input type="hidden" id="'+this.id+'_preventtsubmit'+'" style="display:none"/>' );
      new Insertion.After( this.textInput,
                           '<input type="hidden" name="'+this.id+'_hidden'+'" id="'+this.id+'_hidden'+'"/>' );

      this.createSuggestionsDiv();
   },
	
   handleTextInput: function() {
     var previousRequest    = this.lastRequestString;
	 	this.lastRequestString =this.textInput.value;
	 
     if ( this.lastRequestString == "" ){

        this.hideSuggestions();
	
	 }
     else if ( this.lastRequestString != previousRequest ) {
		$( this.id + "_hidden" ).value="";
		 this.onChangeValue(this);
        this.sendRequestForSuggestions();
     }
   },
 
   moveSelectionUp: function() {

      if ( this.selectedIndex > 0 ) {
         this.updateSelection(this.selectedIndex - 1);
      }
   },
	
   moveSelectionDown: function() {

      if ( this.selectedIndex < (this.suggestions.length - 1)  ) {
         this.updateSelection(this.selectedIndex + 1);
      }
   },

   updateSelection: function(n) {
      var span = $( this.id + "_" + this.selectedIndex );
      if ( span ){
         span.style.backgroundColor = ''//this.options.unSelectionColor;
      }
      this.selectedIndex = n;
      var span = $( this.id + "_" + this.selectedIndex );
      if ( span ){
         span.style.backgroundColor = this.options.selectionColor;
      }
   },


   sendRequestForSuggestions: function() {


     if ( this.handlingRequest ) {

        this.pendingRequest = true;
        return;
     }


     this.handlingRequest = true;
     this.callRicoAjaxEngine();
   },

   callRicoAjaxEngine: function() {
	   

      var callParms = [];
      callParms.push( this.id + '_request');
      callParms.push( 'id='             + this.id);
	  if (this.relatedField != null){
		callParms.push( 'related='        + $(this.relatedField).value);
	  }
	  if (this.relatedField2 != null){
		callParms.push( 'related2='        + $(this.relatedField2).value);
	  }
      callParms.push( 'query='          + this.lastRequestString);
      callParms.push( 'match_anywhere=' + this.options.matchAnywhere);
      callParms.push( 'ignore_case='    + this.options.ignoreCase);
      var additionalParms = this.options.requestParameters || [];
      for( var i=0 ; i < additionalParms.length ; i++ )
         callParms.push(additionalParms[i]);

      ajaxEngine.sendRequest.apply( ajaxEngine, callParms );
   },

   ajaxUpdate: function( ajaxResponse ) {

      this.createSuggestions( ajaxResponse );

      if ( this.suggestions.length == 0 ) {
         this.hideSuggestions();
         $( this.id + "_hidden" ).value = "";
      }
      else {
         this.updateSuggestionsDiv();
         this.showSuggestions();
         this.updateSelection(0);

      }

      this.handlingRequest = false;

      if ( this.pendingRequest ) {

         this.pendingRequest    = false;
         this.handleTextInput();
         this.sendRequestForSuggestions();
      }else{

	  }
   },

   createSuggestions: function(ajaxResponse) {

      this.suggestions = [];
      var entries = ajaxResponse.getElementsByTagName('entry');
      for ( var i = 0 ; i < entries.length ; i++ ) {
        var strText  = this.getElementContent(entries[i].getElementsByTagName('text')[0]);
        var strValue = this.getElementContent(entries[i].getElementsByTagName('value')[0]);
		if (entries[i].getElementsByTagName('extra').length>0){
			var extraField = this.getElementContent(entries[i].getElementsByTagName('extra')[0]);
			this.suggestions.push( { text: strText, value: strValue, extra: extraField} );
		}else{
			this.suggestions.push( { text: strText, value: strValue} );
		}
      }
   },
   setInputFromSelection: function() {

     var hiddenInput = $( this.id + "_hidden" );
     var suggestion  = this.suggestions[ this.selectedIndex ];
     this.textInput.value = suggestion.text;
     hiddenInput.value    = suggestion.value;
     this.hideSuggestions();
	 this.onChangeValue(this);
   },
   showSuggestions: function() {
	  this.spanded = true;	
      var divStyle = this.suggestionsDiv.style;
      

      if ( divStyle.display == 'block' )
         return;
      this.positionSuggestionsDiv();

      divStyle.display = 'block';
   },
	createFrame: function(){
    
        var overID= this.id + "_over";
        this.iFrame=$(overID);
		if (this.iFrame!=null)
		{
			return;
		}
	},				
	
   positionSuggestionsDiv: function() {
	    
        var coordinates = RicoUtil.toDocumentPosition(this.textInput);
        this.x = coordinates.x;
        this.y =coordinates.y + this.textInput.offsetHeight;
     	    

	 
		this.suggestionsDiv.style.left = this.x  + "px";
		this.suggestionsDiv.style.top =  this.y + "px";	
	

		 if(this.suggestions.length > 16 ){
			this.suggestionsDiv.style.height= "200px";
	 	 }
	  	else{
			this.suggestionsDiv.style.height=this.height+"px";
			
	  	}

      if ( this.options.matchTextWidth ){
        /*Ajustado el ancho del suggest manualmente porque no coincide con el ancho del input*/
        this.suggestionsDiv.style.width = (this.textInput.offsetWidth- this.padding()-4) + "px";
    }
	if(this.isIE){
		if(this.iFrame==null){
           		this.createFrame();
		}
// Corrige deplazamiento barra scroll en explorer

        this.suggestionsDiv.style.top = (this.y + document.documentElement.scrollTop) + "px";
        
        this.iFrame.style.position = 'absolute';    

        this.iFrame.style.left = this.x + "px";
        this.iFrame.style.top = (this.y + document.documentElement.scrollTop) + "px";	
        
        this.iFrame.style.zIndex = this.suggestionsDiv.style.zIndex - 1;
        
        this.iFrame.style.width = this.suggestionsDiv.style.width;
        this.iFrame.style.height = this.suggestionsDiv.style.height;
        

        this.iFrame.style.display = "block"; 

	}	

   },
   padding: function() {

     try{
      var styleFunc = RicoUtil.getElementsComputedStyle;
      var lPad    = styleFunc( this.suggestionsDiv, "paddingLeft",      "padding-left" );
      var rPad    = styleFunc( this.suggestionsDiv, "paddingRight",     "padding-right" );
      var lBorder = styleFunc( this.suggestionsDiv, "borderLeftWidth",  "border-left-width" );
      var rBorder = styleFunc( this.suggestionsDiv, "borderRightWidth", "border-right-width" );

      lPad    = isNaN(lPad)    ? 0 : lPad;
      rPad    = isNaN(rPad)    ? 0 : rPad;
      lBorder = isNaN(lBorder) ? 0 : lBorder;
      rBorder = isNaN(rBorder) ? 0 : rBorder;

      return parseInt(lPad) + parseInt(rPad) + parseInt(lBorder) + parseInt(rBorder);
     }catch (e){
      return 0;
     }
   },
   hideSuggestions: function() {
		this.spanded = false;
      this.suggestionsDiv.style.display = 'none';
	  
	  if(this.isIE){
			if(this.iFrame!=null){
				this.iFrame.style.display = 'none';}
	  }
   },
   createSuggestionsDiv: function() {

      this.suggestionsDiv = document.createElement("div");
	 
      this.suggestionsDiv.className = this.options.suggestDivClassName;
      var divStyle = this.suggestionsDiv.style;
      divStyle.position = 'absolute';
      divStyle.zIndex   = 100;
      divStyle.display  = "none";
      
    // añade el div al nodo padre
	$(this.options.parentNode).appendChild(this.suggestionsDiv);


},	
   updateSuggestionsDiv: function() {

		this.suggestionsDiv.innerHTML = "";
	
      var suggestLines = this.createSuggestionSpans();
	  
      for ( var i = 0 ; i < suggestLines.length ; i++ ){
		
			this.suggestionsDiv.appendChild(suggestLines[i]);
	  }
     this.height=suggestLines.length * this.options.ieHeight;	
     this.positionSuggestionsDiv();
	  
   },
   createSuggestionSpans: function() {

      var regExpFlags = "";
      if ( this.options.ignoreCase )
         regExpFlags = 'i';
      var startRegExp = "^";
      if ( this.options.matchAnywhere )
         startRegExp = '';

      var regExp  = new RegExp( startRegExp + this.lastRequestString, regExpFlags );

      var suggestionSpans = [];
      for ( var i = 0 ; i < this.suggestions.length ; i++ )
         suggestionSpans.push( this.createSuggestionSpan( i, regExp ) )

      return suggestionSpans;
   },
   createSuggestionSpan: function( n, regExp ) {

      var suggestion = this.suggestions[n];

      var suggestionSpan = document.createElement("span");
      suggestionSpan.className = this.options.suggestionClassName;
      suggestionSpan.style.width   = '100%';
      suggestionSpan.style.display = 'block';
      suggestionSpan.id            = this.id + "_" + n;
      suggestionSpan.onmouseover   = this.mouseoverHandler.bindAsEventListener(this);
      suggestionSpan.onclick       = this.itemClickHandler.bindAsEventListener(this);

      var textValues = this.splitTextValues( suggestion.text,
                                             this.lastRequestString.length,
                                             regExp );

      var textMatchSpan = document.createElement("span");
	  
      textMatchSpan.id            = this.id + "_match_" + n;
      textMatchSpan.className     = this.options.matchClassName;
	  //textMatchSpan.setAttribute("style","float:left;display:block;");
      textMatchSpan.onmouseover   = this.mouseoverHandler.bindAsEventListener(this);
      textMatchSpan.onclick       = this.itemClickHandler.bindAsEventListener(this);

      textMatchSpan.appendChild( document.createTextNode(textValues.mid) );

      suggestionSpan.appendChild( document.createTextNode( textValues.start ) );
      suggestionSpan.appendChild( textMatchSpan);
      suggestionSpan.appendChild( document.createTextNode( textValues.end ) );
	
	  if (suggestion.extra){
		var extraSpan = document.createElement("span");
		extraSpan.id            = this.id + "_extra_" + n;
		extraSpan.className     = this.options.matchClassName;
		extraSpan.onmouseover   = this.mouseoverHandler.bindAsEventListener(this);
        extraSpan.onclick       = this.itemClickHandler.bindAsEventListener(this);
		extraSpan.innerHTML = suggestion.extra;
		//extraSpan.innerHTML += ' hoteles';
		var dummyDiv = document.createElement("div");
		//dummyDiv.style.display = 'none';
		var dummyTable = document.createElement("table");
		var dummyTr = document.createElement("tr");
		var dummyTd1 = document.createElement("td");
		var dummyTd2 = document.createElement("td");
		dummyTd1.innerHTML = suggestion.text;
		dummyTr.appendChild(dummyTd1);
		dummyTr.appendChild(dummyTd2);
		dummyTable.appendChild(dummyTr);
		dummyDiv.appendChild(dummyTable);
		document.body.appendChild(dummyDiv);
		var w1 = dummyDiv.getElementsByTagName("td")[1].offsetLeft;
		dummyTd1.innerHTML = suggestion.extra;
		var w2 = dummyDiv.getElementsByTagName("td")[1].offsetLeft;
		var margin = (this.textInput.offsetWidth- this.padding()) - w1 - w2;
		if (this.isIE){
			dummyDiv.innerHTML = suggestion.text;
			dummyDiv.innerHTML += suggestion.extra;
			var txt = ' hoteles';
			//dummyDiv.innerHTML += txt;
			dummyDiv.style.width = suggestion.text.length+suggestion.extra.length;
			margin = (this.textInput.offsetWidth- this.padding()) - dummyDiv.offsetWidth;
			//alert(suggestion.text.length+'-'+suggestion.extra.length+'-'+dummyDiv.offsetWidth);
		}
		
		document.body.removeChild(dummyDiv);
		
		extraSpan.style.margin='0px 0px 0px '+margin+'px';
		suggestionSpan.appendChild(extraSpan);
	  }
      return suggestionSpan;
   },
   mouseoverHandler: function(e) {
		
      var src = e.srcElement ? e.srcElement : e.target;
      var index = parseInt(src.id.substring(src.id.lastIndexOf('_')+1));
      this.updateSelection(index);
   },
   itemClickHandler: function(e) {
		
      this.setInputFromSelection();
      this.textInput.focus();
   },
	selectfirstSuggestion: function(pos) {
      var end = this.textInput.value.length;

      if (this.textInput.setSelectionRange) {

		 this.textInput.setSelectionRange(pos,end);
      }
      else if(this.textInput.createTextRange){

		var m = this.textInput.createTextRange();
		m.findText(this.textInput.value.substring(pos));
		m.select();
        
      }
   },
   splitTextValues: function( text, len, regExp ) {

      var startPos  = text.search(regExp);
      var matchText = text.substring( startPos, startPos + len );
      var startText = startPos == 0 ? "" : text.substring(0, startPos);
      var endText   = text.substring( startPos + len );
      return { start: startText, mid: matchText, end: endText };
   },

   getElementContent: function(element) {

      return element.firstChild.data;
   },
   getAnchorPosition: function (anchorname) {

  // ===================================================================
// getAnchorPosition(anchorname)
// This function returns an object having .x and .y 
// properties which are the coordinates
// of the named anchor, relative to the page.
// ===================================================================

	// This function will return an Object with x and y properties
	var useWindow		= false;
	var coordinates	= new Object();
	var x=0,y=0;
	
	// Browser capability sniffing
	var use_gebi=false, use_css=false, use_layers=false;
	if (document.getElementById) { 
		use_gebi=true; 
	}
	else if (document.all) { 
		use_css=true; 
	}
	else if (document.layers) { 
		use_layers=true; 
	}
	
	// Logic to find position
 	if (use_gebi && document.all) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
	}
	else if (use_gebi) {
		var o=document.getElementById(anchorname);
		x=AnchorPosition_getPageOffsetLeft(o);
		y=AnchorPosition_getPageOffsetTop(o);
	}
 	else if (use_css) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
	}
	else if (use_layers) {
		var found=0;
		for (var i=0; i<document.anchors.length; i++) {
			if (document.anchors[i].name==anchorname) { found=1; break; }
			}
		if (found==0) {
			coordinates.x=0; coordinates.y=0; return coordinates;
			}
		x=document.anchors[i].x;
		y=document.anchors[i].y;
	}
	else {
		coordinates.x=0; coordinates.y=0; return coordinates;
	}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
 }
 
   
}


TextSuggestKeyHandler = Class.create();

TextSuggestKeyHandler.prototype = {

   initialize: function( textSuggest ) {

      this.textSuggest = textSuggest;
      this.input       = this.textSuggest.textInput;
      this.addKeyHandling();
   },
   addKeyHandling: function() {
      this.input.onkeyup    = this.keyupHandler.bindAsEventListener(this);
      this.input.onkeydown  = this.keydownHandler.bindAsEventListener(this);
	  this.input.onkeypress     = this.keypressHandler.bindAsEventListener(this);

      if ( this.isOpera )
         this.input.onkeypress = this.keyupHandler.bindAsEventListener(this);
   },
	 	
   keydownHandler: function(e) {
	
      var upArrow   = 38;
      var downArrow = 40;
	  var enterKey  = 13;
	  var keyTab	= 9;	
	 
	  if (e.keyCode== keyTab)
	  {
		this.textSuggest.hideSuggestions();	
	  }	
      else if ( e.keyCode == upArrow ) {
         this.textSuggest.moveSelectionUp();
         setTimeout( this.moveCaretToEnd.bind(this), 1 );
      }
      else if ( e.keyCode == downArrow ){
         this.textSuggest.moveSelectionDown();
      }
	  else if ( e.keyCode == enterKey ){
          return false;
      }
	  
   },
	keypressHandler: function(e){
		var enterKey  = 13;
		if ( e.keyCode == enterKey ){
		  return false;
		}
	},
   keyupHandler: function(e) {
		var enterKey  = 13;
		
      if ( this.input.value.length < 3 && !this.isOpera ){
         this.textSuggest.hideSuggestions();
		 	
	  }	

		if ( !this.handledSpecialKeys(e) && this.input.value.length >= 3  ){
			if (!this.textSuggest.handlingRequest )
				this.textSuggest.handleTextInput();
		}
		if ( e.keyCode == enterKey ){
			  if ( this.textSuggest.suggestionsDiv.style.display == 'block' )
			    this.textSuggest.setInputFromSelection();
			    this.textSuggest.hideSuggestions();
      }
		
   },
   handledSpecialKeys: function(e) {

      var enterKey  = 13;
      var upArrow   = 38;
      var downArrow = 40;
	  

      if ( e.keyCode == upArrow || e.keyCode == downArrow ) {
         return true;
      }
      else if ( e.keyCode == enterKey ) {
        
         return true;
      }
	  
      return false;
   },
   moveCaretToEnd: function() {

      var pos = this.input.value.length;
      if (this.input.setSelectionRange) {
         this.input.setSelectionRange(pos,pos);
      }
      else if(this.input.createTextRange){
         var m = this.input.createTextRange();
         m.moveStart('character',pos);
         m.collapse();
         m.select();
      }
   },
   onblurHandler: function(e) {
	  
	  this.textSuggest.hideSuggestions();
	
   }

};

// ===================================================================
// Functions for IE to get position of an object
// ===================================================================
function AnchorPosition_getPageOffsetLeft (el) 
{
	var ol=el.offsetLeft;
	while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
	return ol;
}
	
// ===================================================================
// ===================================================================	
function AnchorPosition_getWindowOffsetLeft (el) {
	return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
}	
	
// ===================================================================
// ===================================================================	
function AnchorPosition_getPageOffsetTop (el) {
	var ot=el.offsetTop;
	while((el=el.offsetParent) != null) { ot += el.offsetTop; }
	return ot;
}

// ===================================================================
// ===================================================================
function AnchorPosition_getWindowOffsetTop (el) {
	return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
}



