function v_CreateXHR()
{
	if(typeof XMLHttpRequest!='undefined') {return new XMLHttpRequest();};
   	try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {};
   	try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {};
   	return null;
};

function v_CreateHTTPVarSpec(p_xVars) {
	var xSB=new VStringBuilder();
	var bFirst=true;
	for(sKey in p_xVars)
	{
		var xValue=p_xVars[sKey];
		if((typeof xValue)!='function')
		{
			if((typeof xValue)=='string') {xValue=xValue.replace(/\n/g, "\\n");};
	    	xSB.Add(sKey,"=",xValue,"\r\n");
		};
	}
	return xSB.GetString();
};

function v_CreateHTTPVarSpecURL(p_xVars) {
  var sRet="";
  for(sKey in p_xVars)
  {
    var xValue=p_xVars[sKey];
	if((typeof xValue)!='function')
	{
	    sRet+='&'+encodeURIComponent(sKey)+"="+encodeURIComponent(xValue);
	};
  };
  if(sRet.length>0){
    sRet=sRet.substring(1); // chomp initial '&'
  }
  return sRet;
};

function VXHR(p_sURL,p_sFunction)
{
	this.m_sID=v_xXHR.MakeRQID();
	this.m_sFunction=p_sFunction?p_sFunction:"";
	this.m_iTimeout=45000;
	this.m_xTimeStart;
	this.m_xArgs={};
	this.m_xResults={};
	this.m_sResultText="";
	this.m_iTime;
	this.m_iStatus=0;
	this.m_iRetries=0;
	this.m_iTimer=-1;
	this.m_axR=new Array();
	this.m_bComplex=false;
	this.m_sMethod="post";
	this.m_bNoArgs=false;
	this.m_bNoID=false;
	this.m_sURL=p_sURL;
	this.m_bNoJSONResult=false;
	this.m_bWasSent=false;

	this.SetTimeout=function(p_iMilliSecs)
	{
		this.m_iTimeout=p_iMilliSecs;
	};
	this.SetURL=function(p_sURL)
	{
		this.m_sURL=p_sURL;
	};
	this.SetFunction=function(p_sFunction)
	{
		this.m_sFunction=p_sFunction;
	};
	this.SetComplex=function(p_bC)
	{
		this.m_bComplex=p_bC;
	};
	this.ClearParams=function()
	{
		this.m_xArgs={};
	};
	this.SetParams=function(p_sName,p_xArgs)
	{
		if(p_xArgs)
		{
			this.m_xArgs[p_sName]=p_xArgs.ToJSONString();
		};
	};
	this.SetParam=function(p_sName,p_sArg)
	{
		this.m_xArgs[p_sName]=p_sArg;
	};
	this.Send=function()
	{
		v_xXHR.OnStart();
		this.m_iTime=0;
		this.m_xTimeStart=new Date();
		this.m_iRetries=0;
		this.SendInt();
	};
	this.SendNoRetries=function()
	{
		v_xXHR.OnStart();
		this.m_iTime=0;
		this.m_xTimeStart=new Date();
		this.m_iRetries=-1;
		this.SendInt();
	};
	this.SendDelayed=function(p_iMS)
	{
		var xPRq=this;
		if(this.m_iTimer==-1)
		{
			this.m_iTimer=window.setInterval(function(){xPRq.TimeOutCB();},p_iMS);
		};
	};
	this.SendInt=function()
	{
		var xPRq=this;
		var xRq=v_CreateXHR();
		this.m_axR[this.m_iRetries]=xRq;
		if(!xRq){return false;};
		if(!this.m_sURL){return false;};
		this.m_bWasSent=true;
		if(!this.m_bNoID)
		{
			this.m_xArgs["rpc_reqid"]=this.m_sID;
		};
		if(this.m_sFunction)
		{
			this.m_xArgs["rpc_function"]=this.m_sFunction;
		};
		xRq.onreadystatechange = function () {
			if(xRq.readyState!=4){return;};
			var iStatus=0;
			try {
				if(xRq.status==0){return;};
				iStatus=xRq.status;
			} catch (e) {iStatus=-2;}; //FireFox Network error
			
			if(xPRq.m_iTimer!=-1){
				try{window.clearTimeout(xPRq.m_iTimer);}catch (e){};try{window.clearInterval(xPRq.m_iTimer);}catch (e){};
			};
			var sResponse=xRq.responseText;
			v_xXHR.OnStop();
			xPRq.Abort();
			xPRq.m_iStatus=iStatus;
			if(xPRq.m_iStatus==200)
			{
				var xDNow=new Date();
				xPRq.m_iTime=xDNow-xPRq.m_xTimeStart;
				xPRq.m_sResultText=sResponse;
				if(!xPRq.m_bNoJSONResult)
				{
					try {
						xPRq.m_xResults=sResponse.ParseJSON();
					} catch (e) {
						xPRq.m_xResults={};
					};
				};
				if(xPRq.OnSucceed){xPRq.OnSucceed();delete xPRq.OnSucceed;};
				if(xPRq.OnFail){delete xPRq.OnFail;};
			}
			else
			{
				var xDNow=new Date();
				xPRq.m_iTime=xDNow-xPRq.m_xTimeStart;
				xPRq.m_sResultText=sResponse;
				xPRq.m_xResults={};
				if(xPRq.OnFail){xPRq.OnFail();delete xPRq.OnFail;};
				if(xPRq.OnSucceed){delete xPRq.OnSucceed;};
			};
		};
		var xPRq=this;
		if(this.m_iRetries==-1)
		{
			if(this.m_iTimer==-1)
			{
				this.m_iTimer=window.setTimeout(function(){xPRq.TimeOutCB();},this.m_iTimeout);
			};
		}
		else
		{
			if(this.m_iTimer==-1)
			{
				var iTOStep=this.m_iTimeout/6;
				if(iTOStep<1500){iTOStep=1500;};
				this.m_iTimer=window.setInterval(function(){xPRq.TimeOutCB();},iTOStep);
			};
		};
		if(this.m_bComplex)
		{
			var sRB=v_CreateHTTPVarSpec(this.m_xArgs);
			xRq.open("post",this.m_sURL,true);
			xRq.setRequestHeader('Content-Type','text/plain; charset=UTF-8');
			xRq.send(sRB);
		}
		else
		{
			if(this.m_bNoArgs)
			{
				xRq.open(this.m_sMethod,this.m_sURL,true);
				xRq.send("");
			}
			else
			{
				var sRB=v_CreateHTTPVarSpecURL(this.m_xArgs);
				if(sRB.length>0)
				{
					xRq.open(this.m_sMethod,this.m_sURL+"?"+sRB,true);
				}
				else
				{
					xRq.open(this.m_sMethod,this.m_sURL,true);
				};
				xRq.send("");
			};
		};
	};
	this.TimeOutCB=function()
	{
		if((this.m_iRetries>=5)||(this.m_iRetries==-1))
		{
			this.m_iStatus=-3;
			this.Abort();
			if(this.OnFail){this.OnFail();};
		}
		else
		{
			this.m_iRetries++;
			this.SendInt();
		};
	};
	this.Abort=function()
	{
		try{window.clearTimeout(this.m_iTimer);}catch (e){};try{window.clearInterval(this.m_iTimer);}catch (e){};
		this.m_iTimer=-4;
		var i;
		if(this.m_axR)
		{
			for(i=0;i<this.m_axR.length;i++)
			{
				var xR=this.m_axR[i];
				if(xR)
				{
					this.m_axR[i].onreadystatechange=function(){};
					xR.abort();
					this.m_axR[i]=null;
				};
			};
		};
		this.m_iRetries=0;
		this.m_axR.length=0;
		this.m_xResults={};
		this.m_sResultText="";
		v_Purge(this);
	};
	this.OnSucceed=function()
	{
	};
	this.OnFail=function()
	{
	};
};

var v_xXHR=new function() {
	this.m_iRunningCnt=0;
	this.m_iRqIDIterate=1;
	this.m_bShowProgress=true;
	this.m_xRPCProg=document.getElementById("rpcprog");
	
	this.OnStart=function()
	{
		this.m_iRunningCnt++;
		if(this.m_iRunningCnt==1)
		{
			window.setTimeout(function(){v_xXHR.ShowProgress();},200);
		};
	};
	this.OnStop=function()
	{
		this.m_iRunningCnt--;
		if(this.m_iRunningCnt<=0)
		{
			this.HideProgress();
		};
	};
	this.ShowProgress=function()
	{
		if((this.m_iRunningCnt>0)&&(this.m_bShowProgress)&&(this.m_xRPCProg!=null))
		{
			this.m_xRPCProg.style.visibility="visible";
		};
	};
	this.HideProgress=function()
	{
		if((this.m_bShowProgress)&&(this.m_xRPCProg!=null))
		{
			this.m_xRPCProg.style.visibility="hidden";
		};
	};
	
	this.MakeRQID=function()
	{
		this.m_iRqIDIterate++;
		var xNow=new Date();
		var xSB=new VStringBuilder();
		xSB.Add(Math.floor(Math.random()*1000),xNow.getUTCFullYear(),xNow.getUTCMonth(),xNow.getUTCDay(),xNow.getUTCHours(),xNow.getUTCMinutes(),
		xNow.getUTCSeconds(),xNow.getUTCMilliseconds(),this.m_iRqIDIterate,Math.floor(Math.random()*1000));
		return xSB.GetString();
	};
};

