//VARIABLES GLOBALES
// Se colocan fuera de la clase, para que sean comunes a todas las instancias de
// los objetos que se creen, incluso comunes a cualquier parte del codigo js.
// Si cada llamada ajax es asignada con un identificador, todos los estados de cada
// llamadas son accesibles entre ellos y desde fuera.
// El identificador no se asigna automaticamente para evitar un crecimiento desmedido
// de los arrays de estado.

//ESTADOS
var bLoading		= new Array();
var bLoaded 		= new Array();
var bInteractive 	= new Array();
var bComplete 		= new Array();
var bCodRespuesta 	= new Array();
var tLoading 		= new Array();

//DATOS DE LAS LLAMADAS
var __sURL   	= new Array();
var __sVars 	= new Array();
var __fnDone	= new Array();
var __sMethod	= new Array();

var timestampInicio;
var timestampInicioProceso;
var maxIdAjaxPosible = 50;
for (var i=1;i<maxIdAjaxPosible;i++) { tLoading[i] = 0; }

function XHConn()
{

////////////////////////////////////////////////////////

	//PROPIEDADES PUBLICAS

	var reconectarSi;
	this.reconectarSi = new Array();
	var countReconexiones;
	this.countReconexiones = new Array();
	var reconectarAlternativo;
			this.reconectarAlternativo = new Array();
			this.reconectarAlternativo['URL'] = new Array();
			this.reconectarAlternativo['sMethod'] = new Array();
			this.reconectarAlternativo['sVars'] = new Array();
			this.reconectarAlternativo['fnDone'] = new Array();
	var asincrono;
			this.asincrono = true;

	var tiempoCaducidadIdAjax
	this.tiempoCaducidadIdAjax = 120.0;

	//404
	this.reconectarSi['404'] = 2;
	this.countReconexiones['404'] = 0;

	//Timeout
	var tiempoTimeout;
	this.tiempoTimeout = 60; //segundos
	
	this.reconectarSi['timeout'] = 2;
	this.countReconexiones['timeout'] = 0;


	//PROPIEDADES PRIVADAS
	var xmlhttp;

  var nCount=0;
  var idTimeout = new Array();
  var me = this;
  var nproc = 0;

////////////////////////////////////////////////////////

	//CONSTRUCTOR
  try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
  catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
  catch (e) { try { xmlhttp = new XMLHttpRequest(); }
  catch (e) { xmlhttp = false; }}}

  if (!xmlhttp) { return null; }

	timestampInicioProceso = new Date().getTime()/1000.0;

////////////////////////////////////////////////////////

	// METODOS PUBLICOS
	this.abortar = function()
	{
		if (!bComplete[nproc])
		{
			xmlhttp.abort();			
			bComplete[nproc] = true;
		}
	}

	// METODOS PUBLICOS
	this.abortarPorTimeout = function()
	{
		if (!bComplete[nproc])
		{
			if (me.countReconexiones['timeout'] < me.reconectarSi['timeout'])
			{
				me.abortar();
				me.countReconexiones['timeout']++;

  			//RECONSTRUIMOS EL OBJ xmlhttp
  			try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
  			catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
  			catch (e) { try { xmlhttp = new XMLHttpRequest(); }
  			catch (e) { xmlhttp = false; }}}

			me.connect(__sURL[nproc], __sMethod[nproc], __sVars[nproc], __fnDone[nproc], nproc);
			} else {
				me.abortar();
			}
		}
	}

  this.connect = function(sURL, sMethod, sVars, fnDone)
  {
		//OBTENER ID
		var iCount=1;
		var idObjAjax=0;

		var t = (new Date().getTime()/1000.0);
		while (tLoading[iCount] > t  &&  iCount < maxIdAjaxPosible)
		{
			iCount++;
		}
		idObjAjax = iCount;
		tLoading[iCount] = t + this.tiempoCaducidadIdAjax;

		if (idObjAjax > maxIdAjaxPosible || idObjAjax == 0)
		{
	  		return false;
	  	}

  	//ASIGNACION A VBLES GLOBALES
  	__sURL[idObjAjax] 		= sURL;
  	__sVars[idObjAjax] 		= sVars;
  	__fnDone[idObjAjax] 	= fnDone;
  	__sMethod[idObjAjax] 	= sMethod;

  	nproc = idObjAjax;

    bLoaded[idObjAjax] 			= false;
    bInteractive[idObjAjax] = false;
    bComplete[idObjAjax] 		= false;
    bCodRespuesta[idObjAjax]= false;

    idTimeout[idObjAjax] = setTimeout(me.abortarPorTimeout, this.tiempoTimeout * 1000);

    sMethod = sMethod.toUpperCase();

    try {
    	switch (sMethod)
    	{
    	case "GET":
        	xmlhttp.open(sMethod, sURL+"?"+sVars, this.asincrono);
        	sVars = "";
        	break;
      	case "POST":
	        xmlhttp.open(sMethod, sURL, this.asincrono);
  	      xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
    	    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    	    break;
      }

	xmlhttp.onreadystatechange = function()	{	__onreadystatechange(xmlhttp,fnDone,idObjAjax,idTimeout,me);	};
      xmlhttp.send(sVars);
      if (!this.asincrono) { clearTimeout(idTimeout[idObjAjax]); fnDone(xmlhttp,idObjAjax);  }
    }
    catch(z) {
    	 return false;  
    }
    return true;
  };

////////////////////////////////////////////////////////

	//METODOS PRIVADOS
__onreadystatechange = function(xmlhttp,fnDone,idObjAjax,idTimeout,obj)
  {
  	//if (xmlhttp.readyState == 1) { alert('POST: enviando');	}
    switch(xmlhttp.readyState)
    {
    	case 1:
    		if (!bLoading[idObjAjax])
    		{
    			bLoading[idObjAjax] = true;
    		}
    		break;
    	case 2:
    		if (!bLoaded[idObjAjax])
    		{
    			bLoaded[idObjAjax] = true;
    			clearTimeout(idTimeout[idObjAjax]);
    		}
    		break;
    	case 3:
    		if (!bInteractive[idObjAjax])
    		{
    			bInteractive[idObjAjax] = true;
    			clearTimeout(idTimeout[idObjAjax]);
    		}
    		break;
    	case 4:
    		var bExecFnDone = 1;
    		clearTimeout(idTimeout[idObjAjax]);
      	if (!bComplete[idObjAjax])
    		{
      		bComplete[idObjAjax] = true;
      		if (bExecFnDone)
      			{
      			fnDone(xmlhttp,idObjAjax);
      			}
 		}

    		if (bExecFnDone && ( (bLoaded[idObjAjax] && !bInteractive[idObjAjax]) || (xmlhttp.responseText == "" && document.all) ) )
    		{
    			bComplete[idObjAjax] = true;
   				bCodRespuesta[idObjAjax] = xmlhttp.status;

					try {
						if (me.countReconexiones[xmlhttp.status] < me.reconectarSi[xmlhttp.status] && typeof(obj)=="object")
						{
							me.countReconexiones[xmlhttp.status]++;
							obj.connect(__sURL[idObjAjax], __sMethod[idObjAjax], __sVars[idObjAjax], __fnDone[idObjAjax], idObjAjax);
						}
					} catch(z) {	}
			    bLoading[idObjAjax]			= false;
			    bLoaded[idObjAjax] 			= false;
			    bInteractive[idObjAjax] = false;
	   	}
    		break;
    	default: //NADA
    }
  };

  return this;
} // FIN DE LA CLASE


////////////////    COMPATIBILIDAD HACIA ATRAS      /////////////////////////////

			function validaCerrojo(){
				if (linksAbiertos==0){
					return false;
				}
				linksAbiertos=0;
				return true;
			}
			function offCerrojo(){
				setTimeout("linksAbiertos=1;",300);
				}
			function onCerrojo(){
				linksAbiertos=0;
			}

