/**
 * Objeto de Controle e Manipulação em Ajax
 *
 * @code
 *    var oAjax  = new ajax(); //VAR GLOBAL NO ARQUIVO
 *    function ExecutaAjax(){
 *        var codigoRequest = oAjax.init('PAGE', AJAX_ASYNC, AJAX_XML, AJAX_POST);
 *        setLoad(codigoRequest, 'ID_LOADING');
 *        oAjax.setQueryString(codigoRequest, 'NAME_PARAM','VALUE_PARAM');
 *        oAjax.setUserFunction(codigoRequest, USER_FC);
 *        oAjax.setInvokeParam(codigoRequest, VALUE_PARAM);
 *        oAjax.broadcast(codigoRequest);
 *    }

 *    // FUNCAO DE RETORNO
 *    function USER_FC(codigoRequest, ARRAY_USER_FC_PARAMS){
 *        oAjax.xml[codigoRequest].childNodes[1] ...
 *    }
 *
 * @author Iuri Andreazza
 * @since 03/10/2005
 * @version 0.1.0-beta
 * @see XMLHTTPRequest
 */

// Tipo Resposta
var AJAX_XML   = 'xml';
var AJAX_TEXT  = 'text';

// Sincronismo
var AJAX_SYNC  = false;
var AJAX_ASYNC = true;

// Metodo
var AJAX_POST  = 'POST';
var AJAX_GET   = 'GET';
var AJAX_HEAD  = 'HEAD';
var AJAX_MIXED = 'MIXED';

function ajax(){
	// Obj XMLHTTPREQUEST
	this.requester;
	this.indexRequester = 0;

	//true = Async, false = Sync
	this.typeSync;

	// Query String (Parsed)
	this.queryString;

	// Valores do Query String
	this.valuesQueryString;

	// Nome das variaveis no Query String
	this.namesQueryString;

	// Pagina para aonde o Send vai ser dado
	this.namePage;

	// Metodo de Envio do Request
	this.method;

	// Mensagem de Erro.
	this.error = '';

	// Resposta TEXT
	this.text;

	// Resposta TEXT
	this.xml;

	//Tipo de resposta
	this.typeResponce;

	//debug Mode :: True = Active | False = not Active
	this.debug = false;

	//User Func
	this.invoke;
	this.invokeParam;

	//Loading Img
	this.loadDiv;

	// se Eh o IE TOSCO
	this.isIE = false;

    this.onErrorFunction;

	this._construct();
}

ajax.prototype._construct = function(){
	this.requester         = new Array();
	this.typeSync          = new Array();
	this.method            = new Array();
	this.namePage          = new Array();
	this.typeResponce      = new Array();
	this.error             = new Array();
	this.text              = new Array();
	this.xml               = new Array();
	this.invoke            = new Array();
	this.invokeParam       = new Array();
	this.loadDiv           = new Array();
	this.valuesQueryString = new Array();
	this.namesQueryString  = new Array();
	this.queryString       = new Array();
	this.onErrorFunction   = new Array();
	this.onProgress        = new Array();
}

/**
 * Inicializa o Obj Ajax
 *
 */
ajax.prototype.init = function(pageToSend, typeSync, typeResponce, typeMethod){
	try{
		this.requester[this.indexRequester] = new XMLHttpRequest();
		this.isIE = false;
	}catch(error){
		try{
			this.requester[this.indexRequester] = new ActiveXObject("Msxml2.XMLHTTP");
			this.isIE = true;
		}catch(error2){
			try{
				this.requester[this.indexRequester] = new ActiveXObject("Microsoft.XMLHTTP");
				this.isIE = true;
			}catch(error3){
				this.requester[this.indexRequester] = false;
				this.isIE = false;
				this.error[this.indexRequester] = 'Could not inicialize ajax engine.';
			}
		}
	}
	this.onErrorFunction[this.indexRequester] = null;
	
	if(BrowserDetect.browser == 'Firefox'){
	    AJAX_SYNC = true;
	}
	
	if (this.error != ''){
		alert(this.error[this.indexRequester]);
	}else{
		this.valuesQueryString[this.indexRequester] = new Array();
		this.namesQueryString[this.indexRequester]  = new Array();
		this.queryString[this.indexRequester]       = '';
		this.invokeParam[this.indexRequester]  = new Array();
		this.typeSync[this.indexRequester]     = typeSync;
		this.typeResponce[this.indexRequester] = typeResponce;
		this.method[this.indexRequester]       = typeMethod;
		this.namePage[this.indexRequester]     = pageToSend;
		this.setOnReadyFunction(this.indexRequester);
		this.indexRequester++;
		return this.indexRequester-1;
	}
}
/**
 * adiciona um parametro ao 2º parametro da funcao do usuario
 *
 *
 * @param int indRequester
 * @param string paramValue
 */
ajax.prototype.setOnErrorFunction = function(indRequester,func){
	this.onErrorFunction[indRequester] = func;
}
/**
 * Adiciona uma Função do usuário a ser executada a cada passo de progresso feito pela Chamada AJAX.
 *
 *
 * @param int indRequester
 * @param string paramValue
 */
ajax.prototype.setOnProgress = function(indRequester,func){
	this.onProgress[indRequester] = func;
}

/**
 * adiciona um parametro ao 2º parametro da funcao do usuario
 *
 *
 * @param int indRequester
 * @param string paramValue
 */
ajax.prototype.setInvokeParam = function(indRequester,paramValue){
	this.invokeParam[indRequester].push(paramValue);
}

/**
 * Seta a função onreadystatechange
 *
 * @param Func
 */
ajax.prototype.setOnReadyFunction = function(indRequester){
		this.requester[indRequester].onreadystatechange = function(){
		                                                             fncReady(indRequester);
		                                                            };
}

/**
 * Seta os parametros
 *
 * @param indRequester
 * @param string nameParam
 * @param string param
 */
ajax.prototype.setQueryString = function(indRequester, nameParm, param){
	this.namesQueryString[indRequester].push(nameParm);
	this.valuesQueryString[indRequester].push(param);
}

/**
 * Pega o status se está pronto ou nao o Request da função.
 *
 * @param indRequester
 */
ajax.prototype.getReadyStatusRequest = function(indRequester){
	return this.requester[indRequester].readyState;
}

/**
 * Retorna o Status do request, 200 se for OK, 404 se nao achou a pagina ....
 *
 * @param indRequester
 */
ajax.prototype.getStatusRequest = function(indRequester){
	try{
		return this.requester[indRequester].status;
	}catch (e){
		alert('Exception: '+e);
	}
}

/**
 * Da um send em uma variavel no modo POST
 *
 * @param indRequester
 * @param query
 */
ajax.prototype.post = function(indRequester, query){
	try{
		this.requester[indRequester].send(query);
	}catch(e){
		alert('Exception: '+e);
	}
}

/**
 * Traduz os nomes e valores dos paramestros passados para um formato de URL
 *
 * @param indRequester
 */
ajax.prototype.parseQuery = function(indRequester){
	var aux = '';
	for(var i=0; i< this.namesQueryString[indRequester].length; i++){
		aux += this.namesQueryString[indRequester][i]+"="+this.valuesQueryString[indRequester][i]+"&";
	}
	this.queryString[indRequester] = aux;
}

/**
 * Seta o tipo de Header que o formulario irá dar um send
 *
 * @param indRequester
 * @param headerType
 * @param Value
 */
ajax.prototype.setHeaders = function(indRequester, headerType, Value){
	this.requester[indRequester].setRequestHeader(headerType,Value);
}

/**
 * inicia a transmição de dados do browser ao servidor
 *
 * @param indRequester
 */
ajax.prototype.broadcast = function(indRequester){
	if (this.method[indRequester] == 'POST'){
		this.parseQuery(indRequester);
		this.requester[indRequester].open(this.method[indRequester], this.namePage[indRequester], this.typeSync[indRequester]);
		this.setHeaders(indRequester, "Content-Type", "application/x-www-form-urlencoded");
		this.post(indRequester, this.queryString[indRequester]);
	}

	if (this.method[indRequester] == 'GET'){
		this.parseQuery(indRequester);
		this.requester[indRequester].open(this.method[indRequester], this.namePage[indRequester]+'?'+this.queryString[indRequester], this.typeSync[indRequester]);
		this.setHeaders(indRequester, "Content-Type", "application/x-www-form-urlencoded");
		this.post(indRequester, null);
	}

	if (this.method[indRequester] == 'HEAD'){
		this.parseQuery(indRequester);
		this.requester[indRequester].open(this.method[indRequester], this.namePage[indRequester]+'?'+this.queryString[indRequester], this.typeSync[indRequester]);
		this.post(indRequester, null);
	}

	//TO IMPLEMENT
	if (this.method[indRequester] == 'MIXED'){

	}
}

/**
 * Mostra a Resposta do que voltou no request Ajax
 *
 * @param indRequester
 */
ajax.prototype.dump = function(indRequester){
	alert(this.requester[indRequester].responseText);
}

/**
 * Retorna o Texto de resposta em texto do request ajax.
 *
 * @param indRequester
 * @param type
 * @return String
 */
ajax.prototype.getResponse = function(indRequester, type){
	if (this.debug){
		this.dump();
	}
	switch(type){
		case 'xml':
			return this.requester[indRequester].responseXML;
		break;
		case 'text':
			return this.requester[indRequester].responseText;
		break;
		default:
			return 0;
		break;
	}
}

/**
 * Retorna um Header da responsta do request
 *
 * @param indRequester
 * @param headerName
 * @return String
 */
ajax.prototype.getResponseHeader = function(indRequester, headerName){
	return this.requester[indRequester].getResponseHeader(headerName);
}

/**
 * Retorna um Header da responsta do request
 *
 * @param indRequester
 * @return String
 */
ajax.prototype.getAllResponseHeaders = function(indRequester){
	return this.requester[indRequester].getAllResponseHeaders();
}

/**
 * Callback do usuario para quando o requeste estiver terminado
 *
 * @param indRequester
 * @param func
 */
ajax.prototype.setUserFunction = function(indRequester, func,reAssing){
	this.invoke[indRequester] = func;
}

/**
 * Mostra o Loading no div ou se for async entao mostra o principal
 *
 *
 */
ajax.prototype.setLoadingDiv = function(indRequester, obj){
	this.loadDiv[indRequester] = obj;
}

/**
 * Mostra o Loading no div ou se for async entao mostra o principal
 *
 * @param indRequester
 * @param str
 * @param codeStatus
 */
ajax.prototype.showStatusRequest = function(indRequester, str, codeStatus){
	if(this.loadDiv[indRequester] != ''){
		if(codeStatus != 4){
			try{
				this.loadDiv[indRequester].style.visibility = '';
	//			this.loadDiv[indRequester].style.position = '';
			}catch(ee){}
		}else{
			try{
				this.loadDiv[indRequester].style.visibility = 'hidden';
				//this.loadDiv[indRequester].style.position = 'absolute';
			}catch(ee){}
		}
	}
}


/**
 * Funções Internas do obj XMLHTTPREQUEST nao mexer nelas
 * essas funções sao internas logo nao podem pertencer ao objeto ajax(criado pelo Iuri)
 */

/**
 * Funcao que irá no onreadystatechange aonde trata os possiveis erros e invoca a funcao do usuario retornando o xml ou o
 *
 *
 * @param int indRequester
 */
function fncReady(indRequester){
	var situacaoTexto;
	//Div de status

	var body = document.body;

	// Not Inicialized
	if (oAjax.getReadyStatusRequest(indRequester) == 0){
		oAjax.showStatusRequest(indRequester, 'Inicializando ...', 0);
		if(oAjax.onProgress[indRequester] != null){
			oAjax.onProgress[indRequester](0);
		}
	}

	// Loading
	if (oAjax.getReadyStatusRequest(indRequester) == 1){
		oAjax.showStatusRequest(indRequester, 'Loading ...', 1);
		if(oAjax.onProgress[indRequester] != null){
			oAjax.onProgress[indRequester](1);
		}
	}

	// Loaded
	if (oAjax.getReadyStatusRequest(indRequester) == 2){
		oAjax.showStatusRequest(indRequester, 'Ready...', 2);
		if(oAjax.onProgress[indRequester] != null){
			oAjax.onProgress[indRequester](2);
		}
	}

	// Interactive
	if (oAjax.getReadyStatusRequest(indRequester) == 3){
		oAjax.showStatusRequest(indRequester, 'Runnig...', 3);
		if(oAjax.onProgress[indRequester] != null){
			oAjax.onProgress[indRequester](3);
		}
	}

	// Complete
	if (oAjax.getReadyStatusRequest(indRequester) == 4){
		oAjax.showStatusRequest(indRequester, '', 4);
		if(oAjax.onProgress[indRequester] != null){
			oAjax.onProgress[indRequester](4);
		}
		// Load Suscess
		if (oAjax.getStatusRequest(indRequester) == 200){
			oAjax.xml[indRequester]  = oAjax.getResponse(indRequester, AJAX_XML);
			oAjax.text[indRequester] = oAjax.getResponse(indRequester, AJAX_TEXT);
			oAjax.invoke[indRequester](indRequester, oAjax.invokeParam[indRequester]);
		}

		// created 201
		if (oAjax.getStatusRequest(indRequester) == 201){}

		// Accepted 202
		if (oAjax.getStatusRequest(indRequester) == 202){}

		// Partial Information 203
		if (oAjax.getStatusRequest(indRequester) == 203){}

		// No Response 204
		if (oAjax.getStatusRequest(indRequester) == 204){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,204);
		    }else{
			    var msg =('O servidor nao respondeu aguarde alguns instantes e tente novamente.');
			    alert(msg);
			}
		}

		// Bad request 400
		if (oAjax.getStatusRequest(indRequester) == 400){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,400);
		    }else{
			    var msg =('O servidor retornou um erro e nao pode processar a ação por favor aguarde alguns minutos e tente mais tarde. Error Code: 400');
			    alert(msg);
			}
		}

		// Unauthorized 401
		if (oAjax.getStatusRequest(indRequester) == 401){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,401);
		    }else{
			    var msg =('Acesso negado: não foi possível carregar os dados.Error Code: 401');
			    alert(msg);
			}
		}

		// PaymentRequired 402 ---| NAO USADO(AINDA) |---
		if (oAjax.getStatusRequest(indRequester) == 402){}

		// Forbidden 403
		if (oAjax.getStatusRequest(indRequester) == 403){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,403);
		    }else{
			    var msg =('Acesso negado não foi possível carregar os dados.Error Code: 403');
			    alert(msg);
			}
		}

		// Not found 404
		if (oAjax.getStatusRequest(indRequester) == 404){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,404);
		    }else{
			    var msg =('Erro 404:\nArquivo "'+oAjax.namePage[indRequester]+'" não encontrado.');
			    alert(msg);
			}
		}
		
		// Atuh Proxy Required 407
		if (oAjax.getStatusRequest(indRequester) == 407){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,407);
		    }else{
			    var msg =('Erro 407:\nAutenticação de Proxy Requerida em: '+oAjax.namePage[indRequester]+'');
			    alert(msg);
			}
		}

		// Internal Error 500
		if (oAjax.getStatusRequest(indRequester) == 500){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,500);
		    }else{
		        var msg = 'O servidor retornou um erro e nao pode processar a ação por favor aguarde alguns minutos e tente mais tarde.Error Code: 500';
			    alert(msg);
			}
		}

		// Not implemented 501
		if (oAjax.getStatusRequest(indRequester) == 501){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,501);
		    }else{
			    var msg =('O servidor retornou um erro e nao pode processar a ação por favor aguarde alguns minutos e tente mais tarde.Error Code: 501');
			    alert(msg);
			}
		}

		// Service temporarily overloaded 502
		if (oAjax.getStatusRequest(indRequester) == 502){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,502);
		    }else{
			    var msg =('O servidor retornou um erro e nao pode processar a ação por favor aguarde alguns minutos e tente mais tarde.Error Code: 502');
			    alert(msg);
			}
		}

		// Gateway timeout 503
		if (oAjax.getStatusRequest(indRequester) == 503){
		    if(oAjax.onErrorFunction[indRequester] != null){
		        oAjax.onErrorFunction[indRequester](indRequester,503);
		    }else{
			    var msg =('O servidor retornou um erro e nao pode processar a ação por favor aguarde alguns minutos e tente mais tarde.Error Code: 503');
			    alert(msg);
			}
		}

		//situacaoTexto += 'Falha na conexao. Erro: '+this.requester.status+' - '+this.requester.statusText;
	}
	return 0;
}


/**
 * Seta um div com o visual para o loading enquanto o ajax está a processar o request
 *
 * @param int indRequester
 * @param string divLoad
 */
function setLoad(indRequester, divLoad){
	var objLoad = document.getElementById(divLoad);
	oAjax.setLoadingDiv(indRequester, objLoad);
}


/* ////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////
 */
 
/* detectar o browser */
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();


//Inicialização do Objeto Ajax
var oAjax = new ajax();