//Objet Completer
function Completer (thisName, log, elem, startwhen, servlet, whenready, completiondiv)
{
	this.onAjaxReady = whenready;
	this.Name = thisName;
	this.Log = log;
	this.Elem = elem;
	this.StartChar = startwhen;
	this.Servlet = servlet;
	this.Searched = false;
	this.CompletionDiv = completiondiv;
	this.SearchStr = "";
	this.Separator ="**";
	this.MaxOptions = 10;
	this.Options = null;
	this.Selected = null;

	//IE needs this, so we loose object oriented programmation
	this.Elem.onkeyup	= function(e) {return gLocCompleter.KeyUp(this.getAttribute('id'), e);}
	this.Elem.onkeydown = function(e) {return gLocCompleter.KeyDown(this.getAttribute('id'), e);}
	this.Elem.onclick	= function(e) {gLocCompleter.Clicked();}



	this.UserClicked = function()
	{
		this.SetSelected(null);//remise a zero de la selection
		this.ShowCompletionDiv (false);
	}

	this.SetMaxOptions = function (nb)
	{
		if (nb < 0) nb = 0;
		this.MaxOptions = nb;
	}

	this.ShowCompletionDiv = function (display)
	{
		if (this.CompletionDiv != null)
		{
			display ? (this.CompletionDiv.style.display="block") : (this.CompletionDiv.style.display="none");
		}
	}

	this.Clicked = function ()
	{
		this.UpdateCompletionDiv();
	}

	this.Changed = function ()
	{
		if (this.Elem == null){ return null; this.Log.fine ("elem = " + this.Elem);}

		//si on à une recherche en cours
		if (this.Searched)
		{
			//si notre recherche en cours correspond à ce qu'à tapé l'utilisateur.
			if (this.SearchStr.indexOf(this.Elem.value.slice(0, this.StartChar)) == 0)
			{//alors ne pas refaire de recherche
			}
			else //l'utilisateur à entré autre chose
			{
				//si nous avons assez de chars pour faire une recherche
				if (this.Elem.value.length >= this.StartChar)
				{
					//faire une nouvelle requette
					this.MakeNewRequest(this.Elem.value);
				}
				else //pas assé de chars, ne rien faire
				{
				}
			}
			//il faut aussi mettre à jour notre div

			this.UpdateCompletionDiv();
		}
		else //nous n'avons pas de recherche en cours
		{
			//si nous avons assé de chars pour faire une recherche
			if (this.Elem.value.length >= this.StartChar)
			{
				//faire une nouvelle requette
				this.MakeNewRequest(this.Elem.value);
			}
			else //pas assé de chars, ne rien faire
			{
			}
		}
	}

	this.MakeNewRequest = function (str)
	{
		this.Log.info("Making new completion request for : "+ str);

		var pars = "completethis="+str;
		pars	+= "&separator="+this.Separator;

		var myAjax = new Ajax.Request(
								this.Servlet,
								{
									method: 'post',
									parameters: pars,
									onComplete: this.onAjaxReady
								});

		this.SearchStr = str;
		this.Searched = true;
	}

	this.ajaxReadyStateChange = function (response)
	{
		data = response.responseText;
		this.Log.info("data : " + data);

		if ( (data != "") && (data != null) )
		{
			data = data.split (this.Separator);
			data.pop();
			this.Log.info("Found "+(data.length/2)+" matches");
			this.Options = new Array ();		
			for (var i = 0; i < data.length; i+=2)
			{	//associer le futur ID (dom) avec les data
				temp = data[i];
				while ((data[i] = data[i].replace("'", "&#39;")) != temp) temp = str; //on remplace les quote
				this.Options[("CompleteOption"+((i+2)/2))] = new Array (("CompleteOption"+((i+2)/2)), data[i] + " - " + data[i+1],(i+2)/2);
			}
		}
		else //si il n'y a aucun résultat à notre recherche
		{
			this.Options = null;
		}
		this.UpdateCompletionDiv ();
	}

	this.UpdateCompletionDiv = function ()
	{
		if (this.CompletionDiv == null)
		{
			this.CompletionDiv = $("completionDiv");
			if (this.CompletionDiv == null)
			{
				this.CompletionDiv = document.createElement("div");
				document.body.appendChild(this.CompletionDiv);
			}
		}

		var left  = this.GetElementLeft(this.Elem);
		var top   =  parseInt(this.GetElementTop(this.Elem)) + parseInt(this.GetElementHeight(this.Elem));
		var width = this.GetElementWidth(this.Elem);

		this.Log.fine("elemtop : "+this.GetElementTop(this.Elem)+" elem offsetHeight: "+parseInt(this.Elem.offsetHeight) +" elem width: " +"width = "+this.Elem.offsetWidth + "resulting top : " + top);

		this.CompletionDiv.style.position	= "absolute";
		this.CompletionDiv.id				= "completionDiv";
		this.CompletionDiv.style.left 		= left+'px';
		this.CompletionDiv.style.top  		= top+'px';
		this.CompletionDiv.style.width  	= width + 'px';
		this.CompletionDiv.style.maxWidth  	= width + 'px';

		this.CompletionDiv.innerHTML = this.GenerateHtml (this.GetValidOptions (this.Elem.value, this.Options));


		this.ShowCompletionDiv (true);
	}


	this.GetValidOptions = function (str, data)
	{
		if (data == null) return null;

		if (str == "" || str == null) return data;

		opts = new Array ();
		for (var cle in data)
		{
			 //si l'id COMMENCE par str
			 if (data[cle][1]) if (data[cle][1].indexOf(str) == 0) opts.push (data[cle]);
		}
		
		this.Log.fine ("Typed : " + str +" found " + opts.length + " matches");
		return opts;
	}
	
	this.selectNext = function ()
	{
		var curOptions = document.getElementsByName("CompleteOption");
		if (curOptions == null) {return false;}
		var id = curOptions[0].id;//selectioner le 1er
		
		for (var i = 0; i < curOptions.length; i++)
		{
			if (curOptions[i].id == this.Selected)
			{
				id = (i>=(curOptions.length-1)) ? curOptions[0].id : curOptions[i+1].id;
			}
		}

		this.SetSelected (id);
	}
	
	this.selectPrevious = function ()
	{
		var curOptions = document.getElementsByName("CompleteOption");
		if (curOptions == null) {return false;}
		var id = curOptions[curOptions.length-1].id;//selectioner le dernier
		
		for (var i = 0; i < curOptions.length; i++)
		{
			if (curOptions[i].id == this.Selected)
			{
				id = (i==0) ? (curOptions[curOptions.length-1].id) : (curOptions[i-1].id);
			}
		}
		this.SetSelected (id);
	}

	this.SetSelected = function (id)
	{
		var elem = $(id);
		this.Selected = id;	//si id est null, on aura rien de séléctionné
		
		var curOptions = document.getElementsByName("CompleteOption");
		for (var i = 0; i < curOptions.length; i++)
		{
		
			if(curOptions[i].id == id)
			{
				curOptions[i].setAttribute ("class", "selectedOption");
				curOptions[i].setAttribute ("className", "selectedOption");
				
			}
			else
			{
				curOptions[i].setAttribute ("class", "");
				curOptions[i].setAttribute ("className", "");
			}
		}
	}

	this.GenerateHtml = function (data)
	{
		if (data == null)//si on a eut aucun résultat
		{
			var html = "Aucune ville trouvée";
			return html;
		}
		var html = "<ul>";
		moreoptions = false;
		if (data.length < this.MaxOptions)
		{	indexmax = data.length;}
		else
		{	indexmax = this.MaxOptions;
			moreoptions = true;
		}

		for (var i = 0; i < indexmax; i+=1)
		{
			html += "<li>";
			html += "<a href=\"javascript:void(0)\" ";
			html += "id='"+data[i][0]+"' ";
			html += "name='CompleteOption' ";
			html += "onmouseover=\""+this.Name+".SetSelected(this.id);\" ";
			html += "onclick=\""+this.Name+".CompleteWith(this.id);\" >"+data[i][1]+"</a>";
			html += "</li>";
		}
		if (moreoptions) html += "<li>"+data.length+" résultats, affinez votre recherche.</li>";

		html += "</ul>";

		return html;
	}
	
	this.CompleteWith = function (id)
	{
		selec = $(id);
		if (selec == null) return null;
		if (this.Elem == null) return;
		this.ShowCompletionDiv (false);
		this.Elem.value=selec.innerHTML;
		this.Elem.focus ();
	}

	this.GetElementLeft = function (element)
	{
		var curNode = element;
		var left    = 0;

		do {
			left += curNode.offsetLeft;
			curNode = curNode.offsetParent;

		} while(curNode.tagName.toLowerCase() != 'body');

		return left;
	}

	this.GetElementTop = function (element)
	{
		var curNode = element;
		var top    = 0;

		do {
			top += curNode.offsetTop;
			curNode = curNode.offsetParent;

		} while(curNode.tagName.toLowerCase() != 'body');

		return top;
	}

	this.GetElementHeight = function (element)
	{
		return element.offsetHeight;
	}

	this.GetElementWidth = function (element)
	{
		return element.offsetWidth;
	}
	

	this.KeyDown = function (id)
	{
		// Mozilla
		if (arguments[1] != null) {
			event = arguments[1];
		}

		var keyCode = event.keyCode;

		switch (keyCode) {

			// Tab
			case 9:
				this.ShowCompletionDiv(false);
				return;
				
			// Return/Enter
			case 13:
				if (this.CompletionDiv.style.visibility == "hidden") return true;
				this.CompleteWith(this.Selected);
				this.SetSelected(null);//remise a zero de la séléction
				event.returnValue = false;
				event.cancelBubble = true;
				return false;
				break;

			// Escape
			case 27:
				this.ShowCompletionDiv(false);
				this.SetSelected(null);//remise a zero de la séléction
				event.returnValue = false;
				event.cancelBubble = true;
				return false;
				break;
			
			// Up arrow
			case 38:
				this.selectPrevious ();
				return false;
				break;
			
			// Down arrow
			case 40:
				this.selectNext ();
				return false;
				break;
		}
	}

	this.KeyUp = function (id)
	{
		
		// Mozilla
		if (arguments[1] != null) {
			event = arguments[1];
		}

		var keyCode = event.keyCode;

		switch (keyCode) {
		// Return/Enter
			case 13:
				if (this.CompletionDiv.style.visibility == "hidden") return true;
				this.CompleteWith(this.Selected);
				this.SetSelected(null);//remise a zero de la selection
				event.returnValue = false;
				event.cancelBubble = true;
				return false;
				break;

			case 27:
				this.ShowCompletionDiv(false);
				this.SetSelected(null);//remise a zero de la selection
				event.returnValue = false;
				event.cancelBubble = true;
				return false;
				break;
			
			case 38:
			case 40:
				return false;
				break;

			default:
				this.Changed();
				break;
		}
	}

}




