/**
 * @author Henrique
 */
function Ajax(){
	//Variaveis globais (privadas)
	var self = this;
	var vez = null;
	var fila = new Array();
	var method = 'POST';
	var lastTime = 0;
	var assincrono = true;
	var xmlhttp;
	
	
	novoObjeto();
	setInterval(function() { rotina() },4000);
	
	//cria objeto ajax
	function novoObjeto(){
		try{
			xmlhttp = new XMLHttpRequest();
		}
		catch(ee){
			try{
				xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch(e){
				try{
					xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
				}
				catch(E){
					xmlhttp = false;
				}
			}
		}
	}
	
	//objeto de requisição
	function objRequest(pag,param,val,tipo){
		this.pag = pag;
		this.param = param;
		this.val = val;
		this.tipo = tipo;
	}
	
	//calcula tempo atual
	function UTCTime(){
		var atual = new Date();
		return Date.UTC(atual.getFullYear(),atual.getMonth(),atual.getDate(),atual.getHours(),atual.getMinutes(),atual.getSeconds(),atual.getMilliseconds());
	}
	
	//funcao que realiza requisição
	function ajaxRequest(){
		
		inicialTime = UTCTime();
		
		if(method == "POST")
			xmlhttp.open(method, vez.pag+"?rand="+UTCTime() , assincrono);
		else
		 	xmlhttp.open(method, vez.pag+"?rand="+UTCTime()+"&"+vez.param , assincrono);
			
		//bug firefox
		try{
			xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		}
		catch(e){}
		
		xmlhttp.onreadystatechange = function(){
			
			if (xmlhttp.readyState == 4){
				
				var status = 0;
				
				try{
					status = xmlhttp.status;
				}catch(e){
					novoObjeto();
					return;
				}
	
				//caso seja uma pagina valida
				if(status == 200){
					
					var texto = xmlhttp.responseText;
					
					if(vez.tipo == 2){
						
						if(vez.val != null)
							eval(vez.val + "(texto)");
						
					}else if (vez.tipo == 1){
						
						document.getElementById(vez.val).innerHTML = texto;
						interpretador(texto);
						
					}else if (vez.tipo == 3){
						eval(texto);
					}
					
					lastTime = UTCTime();
					
					if(fila.length > 0){
						
						vez = fila.shift();
						delay();
						
					}else
						vez = null;
					
				}
				// caso ocora algum erro...
	
				else if(status != 0){
					
					inicialTime = UTCTime();
					setTimeout(function() { ajaxRequest() },12000);
					
				}
				
			}
			
		};
		//bug firefox
		try{
			
			if(method == "POST")
				xmlhttp.send(vez.param);
			else
				xmlhttp.send();
			
		}catch(e){}
		
	}
	
	function delay()
	{
		var diferenca = UTCTime() - lastTime;
	
		if(diferenca > 700)
			ajaxRequest();
		else
		{
			diferenca = 700 - diferenca;
			setTimeout(function() { ajaxRequest() },diferenca);
		}
	}
	
	//rotina para verificar se a chamada ajax está demorando para ser respondida
	//caso sim, aborta e inicia novamente
	function rotina()
	{
		if (vez != null) {
			var diferenca = UTCTime() - inicialTime;
			
			if (diferenca > 14000) 
				self.abortar();
		}
	}
	
	/*
		Função que realiza a chamada e interpreta o resultado.
		Ou seja, o resultado neste caso deve ser um código javascript.
		
		param pag: página a ser chamada
		param param: parâmetro a ser passado
	*/
	this.chamadaJSON = function(pag, param){
		
		if(vez == null){
			
			//adiciona para a chamada atual
			vez = new objRequest(pag, param, null, 3);
			//delay, if need
			delay();
			
		}else{
			
			//adiciona chamada na fila
			fila.push(new objRequest(pag,param,null,3));
			
		}
		
	}
	
	/*
		Função realiza a chamada, ao obter o resultado, chama
		a função 'func' com o resultado do parâmetro.
		ex:
			ajax.chamadaFunc('pag.php', 'x=20', 'testar'); irá
			chamar a função 'testar()' passando o resultado ajax
			como parâmetro.
		
			param pag: página a ser feita a chamada
			param param: parâmetro a ser passado
			val: função a ser chamada com o parâmetro 'param'
	*/
	this.chamadaFunc = function (pag, param, val){
		
		if(vez == null){
			
			//adiciona para a chamada atual
			vez = new objRequest(pag, param, val,2);
			//delay, if need
			delay();
			
		}else{
			
			//adiciona chamada na fila
			fila.push(new objRequest(pag, param, val,2));
			
		}
		
	}
	
	/*
		Função que realiza a chamada Ajax e insere, por innerHTML
		o resultado em um elemento com id 'div'.
		
		param pag: página a ser feita a chamada
		param param: parâmetro a ser verificado
		param val: id do elemento no qual receberá o resultado por
					innerHTML
	*/
	this.chamadaDiv = function (pag, param, val){
		
		if(vez == null){
			
			//adiciona para a chamada atual
			vez = new objRequest(pag,param,val,1);
			//delay, if need
			delay();
			
		}else{
			
			//adiciona chamada na fila
			fila.push(new objRequest(pag,param,val,1));
			
		}
		
	}
	
	//altera metodo
	this.setMethod = function(metodo) {
		method = metodo;
	}
	
	//obtem metodo
	this.getMethod = function() {
		return method;
	}
	
	//aborta chamada ajax
	this.abortar = function(){
		xmlhttp.abort();
		ajaxRequest();
	}
	
	//altera tipo do ajax
	this.setAssicrono = function(val) {
		assicrono = val;
	}
	
	//obtem tipo do ajax
	this.getAssicrono = function() {
		return assincrono;
	}
	
	function interpretador(html) {
		var inicio = html.search(/<script>/);
		if(inicio != -1) {
			inicio += 8;
			var fim = html.search(/<\/script>/);
			var script = html.substr(inicio,fim - inicio);
			eval(script);
		}
	}
}

var ajax = new Ajax();

