var AjaxAutoCompletar = function(urlIni, nomeCampo, textBoxID) {
	// Propriedades
	this.listaParametros = [{nome:nomeCampo, valor:""}];
	this.URLInicial = urlIni;
	this.esperarAntesDeChamar = 300;		// Esperar n milesegundos para antes de chamar função
	this.caracteresAntesDeChamar = 3;		// Número de caracteres que deve ter antes de chamar

	// Se caixa de texto não existir, cai fora
	if(!document.getElementById(textBoxID))
		return;	
		
	// Objetos
	this.solicitacao = null;

	// Variaveis para uso interno
	this.timer = null;
	this.timerEsconder = null;
	this.estouVisivel = false;				// ListBox está visível
	this.exibirIFramePorTras = false;		// Exibir IFrame por tras do div do listBox
	this.estouComFocus = false;				// Trata do focus
	this.moverFocoParaTextBox = true;		// Passar foco para caixa de texto
		
	// Elementos
	this.textBox = document.getElementById(textBoxID);
	this.listBox = null;
	this.listBoxTBody = null;
	this.iframePorTras = null;
			
	this.dataList = null;					// Guarda valores retornados pela consulta
	this.selectedIndex = null;				// Item selecionado
	this.itensCount = 0;					// Número de itens
		
	// Anexar ao evento da caixa de texto
	var _this = this;
	this.textBox.onkeyup = function(event){return _this.onKeyUp(event)};
	this.textBox.onkeydown = function(event){return _this.onKeyDown(event)};
	this.textBox.onblur = function(event){_this.onBlur(event)};
	this.textBox.onfocus = function(event){_this.onFocus(event)};

	// Verificar browser
	var nav = ajaxBrowser();
	if(nav.nome == "MSIE" && nav.maior <= 6)
		this.exibirIFramePorTras = true;
	this.navegador = nav;

	// Desabilitar o Autocomplete do IE
	this.textBox.setAttribute("autocomplete", "off");

}

// Eventos
AjaxAutoCompletar.prototype.onKeyDown = function(e) {
	this.keyEnterParaSelecionar = false;
	if(this.estouVisivel) {
		var eve = (window.event ? event : e);
		switch (eve.keyCode) {
			case 38:
			case 37:
				this.moverParaItemAcima();
				return false;
				break;
			case 39:
			case 40:
				this.moverParaItemAbaixo();
				return false;
				break;
			case 13:	// Enter
				this.selecionarItem(this.selectedIndex);
				return false;
				break;
			case 27:	// Esc
				this.esconderListBox();
				break;
			case 9:		// Tab
				this.moverFocoParaTextBox = false;
				this.esconderListBox();
				break;
		}
	}
	return true;
}

AjaxAutoCompletar.prototype.onKeyUp = function(e) {
	var eve = (window.event ? event : e);
	var src = (window.event ? event.srcElement : e.target);
	if(eve.keyCode == 8 || eve.keyCode == 32 || eve.keyCode == 46 || eve.keyCode >= 65) {
		if(this.textBox.value.length >= this.caracteresAntesDeChamar) {
			if(this.timer) clearTimeout(this.timer);
			if(this.solicitacao) this.solicitacao.abortar();
			var _this = this;
			this.timer = setTimeout(function(){_this.consultar()}, this.esperarAntesDeChamar);
		} else {
			this.esconderListBox();
		}
	}
	return true;
}

AjaxAutoCompletar.prototype.onBlur = function(e) {
	this.estouComFocus = false;

	if(this.estouVisivel) {
		var _this = this;
		this.timerEsconder = setTimeout(function(){_this.esconderListBox()}, 300);
	}
	
	// Cancelar consulta
	if(this.timer) {
		clearTimeout(this.timer);
		this.timer = null;
	}
}

AjaxAutoCompletar.prototype.onFocus = function(e) {
	if(this.timerEsconder) {
		clearTimeout(this.timerEsconder);
		this.timerEsconder = null;
	}
	this.estouComFocus = true;
}

// Métodos
AjaxAutoCompletar.prototype.consultar = function() {
	this.timer = null;
	if(this.textBox) {
		if(this.textBox.value.length > 2) {
			var url = this.URLInicial;
			var _this = this;
			var funcao = function(){_this.processarSolicitacao()};
			this.listaParametros[0].valor = this.textBox.value;
			this.solicitacao = new Solicitacao(url, this.listaParametros, funcao);
			this.solicitacao.solicitar();
		}
	}
}

AjaxAutoCompletar.prototype.processarSolicitacao = function() {
	var req = this.solicitacao.request;
	if(req && req.readyState == 4) {
		if(req.status == 200) {
			this.dataList = ajaxConverteTextToList(req.responseText);
			if(this.dataList && this.estouComFocus)
				this.exibirListBox();
			else if(this.estouVisivel)
				this.esconderListBox();
		}
		else {
			//alert("Erro: " + req.status);
		}
	}
}


AjaxAutoCompletar.prototype.criarListBox = function() {

	// Criar IFRAME que vai ficar por tras
	if(this.iframePorTras == null && this.exibirIFramePorTras) {
		var ifra = document.createElement("IFRAME");
		ifra.src = "about:blank";
		ifra.frameBorder = "1";
		ifra.scrolling = "no";
		ifra.style.position = "absolute";
		ifra.style.visibility = "hidden";
		ifra.style.width = "1px";
		ifra.style.height = "1px";
		document.body.appendChild(ifra);
		this.iframePorTras = ifra;
	}

	// Cria div do listBox
	if(this.listBox == null) {
		var div = document.createElement("DIV");
		div.style.position = "absolute";
		div.className = "autocompletar";
		div.style.visibility = "hidden";
		div.style.overflow = "auto";
		document.body.appendChild(div);
		this.listBox = div;

		// Manter o focus sempre na caixa de texto
		var _this = this;
		div.onfocus = function(){_this.textBox.focus()};
	}

	// Tabela para os itens
	if(this.listBoxTBody == null) {
		var tab = document.createElement("TABLE");
		tab.width = "100%";
		tab.cellPadding = 0;
		tab.cellSpacing = 0;
		tab.border = 0;
		var tbody = document.createElement("TBODY");	
		tab.appendChild(tbody);
		this.listBox.appendChild(tab);
		this.listBoxTBody = tbody;
	}
}

AjaxAutoCompletar.prototype.preencherListBox = function() {
	var tbody = this.listBoxTBody;
	if(tbody) {
		var _this = this;
		this.itensCount = this.dataList.length;
		for(var i = 0; i < this.dataList.length; i++) {
			var tr, td;
			if(tbody.childNodes.length > i) {
				tr = tbody.childNodes[i];
				td = tr.firstChild;
			} else {
				td = document.createElement("TD");
				tr = document.createElement("TR");
				tr.appendChild(td);		
				tbody.appendChild(tr);
			}
			td.setAttribute("itemIndex", i);
			td.onclick = function(event){_this.onItemClickEvent(event)};
			td.onmouseover = function(event){_this.onItemMouseOverEvent(event)};
			td.onmouseout = function(event){_this.onItemMouseOutEvent(event)};
			td.innerHTML = this.dataList[i].text;
		}
		//Remover linhas escedentes da tabela
		for(var r = tbody.childNodes.length - 1; r >= this.itensCount; r--) {
			tbody.removeChild(tbody.childNodes[r]);
		}
	}
}

AjaxAutoCompletar.prototype.exibirListBox = function() {
	if(this.dataList) {

		// Criar div se necessário
		this.criarListBox();
		this.listBox.style.height = "";
		
		// Preencher com itens
		this.preencherListBox();

		// Posição e largura da caixa de texto
		var rect = ajaxGetClienteRect(this.textBox);
	
		// Dimensões da área da janela
		var area = {left: document.body.scrollLeft, 
					top: document.body.scrollTop,
					width: document.body.clientWidth,
					height: document.body.clientHeight};
	
		// Altura Máxima para o listBox
		var alturaMaxima = (area.top + area.height) - (rect.bottom + 10);
		var posicionarAcima = false;
		if(alturaMaxima < area.height * 0.3) {
			posicionarAcima = true;
			alturaMaxima = rect.top - (area.top + 10);
		}
			
		//Ajustar altura máxima para a lista
		if(this.listBox.clientHeight > alturaMaxima)
			this.listBox.style.height = ajaxPixels(alturaMaxima);

		// Valores extras para a posição e tamanho
		var extraLeft = 0, extraTop = 0, extraWidth = 0;
		if(this.navegador && this.navegador.nome == "MSIE") {
			//extraTop = 1;
			//extraLeft = 1;
			extraWidth = 4;
		}

		// Posicionar div logo abaixo da caixa de texto
		var listBoxRect = ajaxGetClienteRect(this.listBox);
		if(!posicionarAcima) 
			this.listBox.style.top = ajaxPixels(rect.bottom + extraTop);
		else
			this.listBox.style.top = ajaxPixels(rect.top - listBoxRect.height - 1);
		this.listBox.style.left = ajaxPixels(rect.left + extraLeft);
		this.listBox.style.width = ajaxPixels(rect.width + extraWidth);
		
		// Posicionar Iframe por tras se necessário
		if(this.iframePorTras) {
			this.iframePorTras.style.left = this.listBox.style.left;
			this.iframePorTras.style.top = this.listBox.style.top;
			this.iframePorTras.style.width = this.listBox.style.width;
			this.iframePorTras.style.height = ajaxPixels(listBoxRect.height);
			this.iframePorTras.style.visibility = "visible";
		}
		
		// Mostrar listBox
		this.listBox.style.visibility = "visible";
		this.estouVisivel = true;
		this.moverFocoParaTextBox = true;
	}
}

AjaxAutoCompletar.prototype.esconderListBox = function() {
	if(this.estouVisivel) {
		this.listBox.style.visibility = "hidden";
		this.estouVisivel = false;
		if(!this.estouComFocus && this.moverFocoParaTextBox) this.textBox.focus();
		// Mover para fora da área visível
		this.listBox.style.top = "-1500px";
		this.listBox.style.left = "-1500px";
	}
	
	if(this.iframePorTras && this.iframePorTras.style.visibility == "visible") {
		this.iframePorTras.style.visibility = "hidden";
		// Mover para fora da área visível
		this.iframePorTras.style.top = "-1500px";
		this.iframePorTras.style.left = "-1500px";
	}
	
	this.selectedIndex = null;
	this.moverParaItem(-1);
	this.timerEsconder = null;
}

// Eventos do item
AjaxAutoCompletar.prototype.onItemClickEvent = function(e) {
	var src = (window.event ? event.srcElement : e.target);
	var index = parseInt(src.getAttribute("itemIndex"));
	this.selecionarItem(index);
}

AjaxAutoCompletar.prototype.onItemMouseOverEvent = function(e) {
	var src = (window.event ? event.srcElement : e.target);
	var index = parseInt(src.getAttribute("itemIndex"));
	this.moverParaItem(index);
}

AjaxAutoCompletar.prototype.onItemMouseOutEvent = function(e) {
	this.selectedIndex = null;
	this.moverParaItem(-1);
}

// Metodos para os itens do listBox
AjaxAutoCompletar.prototype.selecionarItem = function(index) {
	if(this.listBox.style.visibility == "visible") {
		if(this.textBox && this.dataList) {
			this.textBox.value = this.dataList[index].text;
			this.esconderListBox();
		}
	}
}

AjaxAutoCompletar.prototype.moverParaItemAcima = function() {
	if(this.listBoxTBody) {
		var index = this.itensCount - 1;
		if(this.selectedIndex != null) {
			if(this.selectedIndex > 0)
				index = this.selectedIndex - 1;
			else if(this.selectedIndex == 0)
				index = this.itensCount - 1;
		}
		this.moverParaItem(index);
	}
}

AjaxAutoCompletar.prototype.moverParaItemAbaixo = function() {
	if(this.listBox && this.listBox.firstChild) {
		var index = 0;
		if(this.selectedIndex != null) {
			if(this.selectedIndex < (this.itensCount - 1))
				index = this.selectedIndex + 1;
			else if(this.selectedIndex == (this.itensCount - 1))
				index = 0;
		}
		this.moverParaItem(index);
	}
}

AjaxAutoCompletar.prototype.moverParaItem = function(index) {
	var div = this.listBox;
	var rctDiv = ajaxGetClienteRect(div);
	var tbody = this.listBoxTBody
	if(tbody) {
		for(var i = 0; i < tbody.childNodes.length; i++) {
			var tr = tbody.childNodes[i];
			var nomeClasse = "";
			if(i == index) {
			 	nomeClasse = "sel";
				var rct = ajaxGetClienteRect(tr);
				var innerTop = rct.top - rctDiv.top;
				var innerBottom = rct.bottom - rctDiv.top;
				if(innerTop < div.scrollTop)
					div.scrollTop = innerTop;
				else if(innerBottom > (rctDiv.height + div.scrollTop))
					div.scrollTop += (innerBottom - (rctDiv.height + div.scrollTop)) ;
				this.selectedIndex = i;
			}
			for(var c = 0; c < tr.childNodes.length; c++) {
				var td = tr.childNodes[c];
				if(td.className != nomeClasse) td.className = nomeClasse;
			}
		}
	}
}
