/*===========================================================================================*/
/**
* @throws	Error	Si el browser no soporta AJAX.
*/
function AJAXHandler()
{
	var me = this;
	this.handler = null;
	this.responseText = null;
	this.responseXML = null;

	/* Status constants */
	this.ST_UNINITIALIZED	= 0;
	this.ST_LOADING			= 1;
	this.ST_LOADED			= 2;
	this.ST_INTERACTIVE		= 3;
	this.ST_COMPLETE		= 4;
	/*=============================================*/
	/**
	*	Inicializar XMLHttpRequest / ActiveXObject
	*/
	this.init = function() {
		if (window.XMLHttpRequest)
		{
			this.handler = new XMLHttpRequest();
		}
		else
		{
			try
			{
				this.handler = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {
				try
				{
					this.handler = new ActiveXObject("Msxml2.XMLHTTP");
				} catch (e) {
					this.handler = null;
					throw new Error("Your browser does not support AJAX.\n\nPlease update your browser.");
				}
			}
		}
	};
	
	/**
	*	Setear funcion que se ejecuta en cambio de estado
	*	@param	function
	*/
	this.setReadyStateListener = function (func) {
		if (!this.handler) return;
		this.handler.onreadystatechange = func;
	};
	
	/**
	*	Setear funcion que se ejecuta onload
	*	@param	function
	*/
	this.setLoadListener = function (func) {
		this.setReadyStateListener(function() {
			if (me.ready()) func();
		});
	};

	/**
	*	Obtener estado
	*	@return	integer
	*/
	this.getReadyState = function() {
		return this.handler.readyState;
	};
	
	/**
	*	Obtener respuesta del servidor http (200 = ok)
	*	@return	integer
	*/
	this.getStatus = function() {
		return this.handler.status;
	};
	
	/**
	*	Obtener texto recibido
	*	@return	string
	*/
	this.getText = function() {
		return (this.responseText !== null) ? this.responseText : this.handler.responseText;
	};
	
	/**
	*	Obtener XML recibido
	*	@return	object	XmlDocument
	*/
	this.getXML = function() {
		return (this.responseXML !== null) ? this.responseXML : this.handler.responseXML;
	};
	
	/**
	*	Abortar request
	*/
	this.abort = function() {
		this.handler.abort();
	};
	
	/**
	*	Determinar si se completo el request
	*	@return	boolean
	*/
	this.ready = function() {
		if (this.getReadyState() == this.ST_COMPLETE && this.getStatus() == 200)
		{
			this.responseText = this.handler.responseText;
			this.responseXML = this.handler.responseXML;
			if (IE) this.abort();
			return true;
		}
		return false;
	};

	/**
	*	Enviar request al server
	*	@param	string	metodo: POST | GET 
	*	@param	string	cadena de variables a enviar
	*	@param	string	archivo que recibe el request
	*	@param	boolean	sincronico / ascincronico
	*/
	this.request = function(method, URI, dest, async) {
		if (!this.handler || (this.handler.readyState != this.ST_UNINITIALIZED && this.handler.readyState != this.ST_COMPLETE)) return;
		if (typeof dest == 'undefined') var dest = window.location.href;
		if (typeof async == 'undefined') var async = true;
		if (method == 'POST')
		{
			this.handler.open("POST", dest, async);
			this.handler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			this.handler.send(URI);
		}
		else
		{
			dest = (dest.split('?')[1]) ? dest + '&' + URI : dest.replace(/\?/, '') + '?' + URI;
			this.handler.open("GET", dest, async);
			this.handler.send(null);
		}
	};

	/**
	*	Muestra mensaje de estado en un contenedor de bloque
	*	@param	string		texto a mostrar
	*	@param	string|null	(opcional) id del objeto donde mostrar el texto
	*	@param	boolean		(opcional) centrar en el viewport
	*	@param	string|null	path a imagen de 'loading'
	*/
	this.showStatus = function(msg, oID, center, loadingImageSrc) {
		var o, customStatus = false;
		if (typeof center != 'boolean') var center = false;
		if (oID && (o = document.getElementById(oID)) != null)
			customStatus = true;
		else
			o = document.getElementById('ajax_handler__status');
		if (o == null)
		{
			var div = document.createElement('div');
			div.id = 'ajax_handler__status';
			div.style.position = (OLD_IE) ? 'absolute' : 'fixed';
			div.style.border = '1px solid #000';
			div.style.padding = '6px';
			div.style.backgroundColor = '#DDEEFF';
			div.style.color = '#000';
			div.style.fontFamily = 'Arial';
			div.style.fontWeight = 'bold';
			div.style.fontSize = '11px';
			document.body.appendChild(div);
			o = div;
		}
		if (this.getReadyState() == this.ST_LOADING)
		{
			o.innerHTML = (loadingImageSrc) ? '<div style="margin-bottom:3px; text-align:center;"><img src="'+loadingImageSrc+'" alt="" /></div>' + msg : msg;
			o.style.display = 'block';
			if (center)
			{
				if (OLD_IE)
				{
					var centerDiv = function() {
						var dimXY = getMaxXY();
						var scrollXY = getScrollXY();
						o.style.left = dimXY[0] / 2 + scrollXY[0] - o.offsetWidth / 2 + 'px';
						o.style.top = dimXY[1] / 2 + scrollXY[1] - o.offsetHeight / 2 + 'px';
					};
					o.style.position = 'absolute';
					centerDiv();
					window.attachEvent('onscroll', centerDiv);
				}
				else
				{
					o.style.position = 'fixed';
					o.style.left = '50%';
					o.style.top = '50%';
					o.style.marginLeft = -(o.offsetWidth/2) + 'px';
					o.style.marginTop = -(o.offsetHeight/2) + 'px';
				}
			}
			else if (!customStatus)
			{
				if (OLD_IE)
				{
					var fixDiv = function() {
						o.style.left = 2 + getScrollXY()[0] + 'px';
						o.style.top = 2 + getScrollXY()[1] + 'px';
					};
					fixDiv();
					window.attachEvent('onscroll', fixDiv);
				}
				else
				{
					o.style.left = '2px';
					o.style.top = '2px';
				}
			}
		}
		else if (this.getReadyState() == this.ST_COMPLETE)
		{
			o.style.display = 'none';
		}
	};
	/*=============================================*/
	/* Inicializar */
	this.init();
}