var xmlreqs = new Array();
var xmlreqsTime = new Array();
var httpStatus = new Array();
var debugProcTime = false;

//var xmreqsAverage = 30;

function CXMLReq(freed) {
	this.freed = freed;
	this.xmlhttp = false;
	if (window.XMLHttpRequest) {
		this.xmlhttp = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
}

function ajaxProcTime(mssinceepoch) {
	
	
	
	////////////
	//
	//debug info
	//
	debugProcTime = mssinceepoch;
	spandebugNum = document.getElementById("debugNum");
	//alert(mssinceepoch);
	if (spandebugNum !== null) {
		removeChildren(spandebugNum);
		spandebugNum.appendChild(document.createTextNode(mssinceepoch));
	}
	
	
	//alert('ts: '+ts);
	//var currentTime = new Date();
	//var ctss = currentTime.getTime() - ts;
	//if (ctss>30000) { ctss = 30000; }
	//alert('ts: '+ctss);
	//return null;
	var l = xmlreqsTime.length;
	if (l>4) {
		xmlreqsTime.reverse();
		xmlreqsTime.pop();
		xmlreqsTime.reverse();
		var l = xmlreqsTime.length;
	}
	xmlreqsTime[l] = mssinceepoch;
	//xmlreqsMin = ctss;
	//xmlreqsMax = ctss;
}

function ajaxCalcAverage() {
	var xmreqsAverage = 100;
	var currentTime = new Date();
	var tst = 0;
	var tsTxt = "";
	//var ats = AjaxChatPollIntervalMs;
	//alert(ats);
	var l = xmlreqsTime.length;
	var ti = l;
	if (l>0) {
		for (i=0; i!=l; i++) {
			tst += xmlreqsTime[i];
			tsTxt += " + " + xmlreqsTime[i];
			//if (xmlreqsTime[i]>xmlreqsMax) { xmlreqsMax = xmlreqsTime[i]; }
			//if (xmlreqsTime[i]<xmlreqsMin) { xmlreqsMin = xmlreqsTime[i]; }
		}
		//if (l>9) {
		//	tst -= xmlreqsMin - xmlreqsMax;
		//	tst += xmlreqsTime[(l-1)] + xmlreqsTime[(l-1)] + xmlreqsTime[(l-1)];
		//	tst += xmlreqsTime[(l-2)] + xmlreqsTime[(l-2)];
		//	l += 3;
		//}
	}
	
	var l = xmlreqs.length;
	if (l>0) {
		
		for (var i=0; i<l; i++) {
			if (xmlreqs[i].freed == 0) {
				msbusy = currentTime.getTime() - xmlreqs[i].ts;
				if (msbusy>2000) {
					ti++;
					tst += msbusy;
					tsTxt += " + " + msbusy;
				}
			}
		}
	
	
	

		
		//alert(xmreqsAverage);
	}
	
	if (ti>0) {
		//ats = Math.round(tst/ti);
		xmreqsAverage = Math.round(tst/ti);
		tsTxt += " = " + tst + ", gedeeld door " + ti + " is " + xmreqsAverage;
	}
	
	//alert(tst);
	//check number of uncompleted ajax calls (higher number suggest server/connection problem, time-out)
	//var l = xmlreqs.length;
	//if (l>0) {
	//	var acalls = 0;
	//	for (var i=0; i<l; i++) {
	//		if (xmlreqs[i].freed == 0) {
	//			acalls++;
	//		}
	//	}
	//	//alert(acalls);
	//	if (ats>6000 && acalls<1) { //number of uncompleted calls is lower than the average call duration would suggest, suggesting connection is restored/improved, therefore intervene and decrease interval to 6000
	//		//ats = 6000;
	//		//tsTxt += ' --- intervention: down to 6000';
	//		
	//		
	//	}
	//	if (ats<4000 && acalls>3) { //number of uncompleted calls is higher than the average call duration would suggest, suggesting there is connection problem at hand, therefore intervene and increase interval to 4000 
	//		//ats = 4000;
	//		//tsTxt += ' --- intervention: up to 4000';
	//	}
	//}
	//xmreqsAverage = ats;
	
	if (xmreqsAverage>30000) {
		//alert('server slow');
		server_slow();
	} else {
		server_ok();
	}
	
	//aaMsg = new Array();
	//aaMsg['ID'] = '';
	//aaMsg['ts'] = currentTimestamp();
	//aaMsg['sender'] = member;
	//aaMsg['msg'] = tsTxt;
	//aaMsg['alert'] = 'n';
	//appendMsg(aaMsg);
	//scrollDown();
	
	//return xmreqsAverage;


}

function ajaxCall(url, params, method, forcecall) {
	
	ajaxCalcAverage();
	
	var pos = -1;
	var busy = 0;
	var currentTime = new Date();
	var l = xmlreqs.length;
	for (var i=0; i<l; i++) {
		var x = xmlreqs[i].timeout-currentTime.getTime(); //this is to check whether the connection has served it's timeout
		if (xmlreqs[i].freed == 1 && x<0) {
			pos = i;

			//aaMsg = new Array();
			//aaMsg['ID'] = '';
			//aaMsg['ts'] = currentTimestamp();
			//aaMsg['sender'] = member;
			//aaMsg['msg'] = xmlreqs[i].timeout + " - " + currentTime.getTime() + " = " + x + ", GOED.";
			//aaMsg['alert'] = 'n';
			//appendMsg(aaMsg);
			//scrollDown();
			//break;
		} else {
			busy++;
			//aaMsg = new Array();
			//aaMsg['ID'] = '';
			//aaMsg['ts'] = currentTimestamp();
			//aaMsg['sender'] = member;
			//aaMsg['msg'] = xmlreqs[i].timeout + " - " + currentTime.getTime() + " = " + x + ", NIET goed." + busy;
			//aaMsg['alert'] = 'n';
			//if (xmlreqs[i].freed == 1) {
			//	appendMsg(aaMsg);
			//	scrollDown();
			//}

		}
	}
	if (busy > 0 && forcecall != true) { //cancels call if 2 queries currently waiting, unless force == true
		//server_slow();
		return null;
	} else if (pos == -1) { 
		pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1);
	}
	
	//alert(xmlreqs.length);
	if (xmlreqs[pos].xmlhttp) {
		
		currentTime = new Date();
		xmlreqs[pos].ts = currentTime.getTime();
		xmlreqs[pos].timeout = currentTime.getTime();
		xmlreqs[pos].freed = 0;		
		if (method == 'post') {
			xmlreqs[pos].xmlhttp.open("POST",url,true);
			xmlreqs[pos].xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			xmlreqs[pos].xmlhttp.setRequestHeader("Content-length", params.length);
			//xmlreqs[pos].xmlhttp.setRequestHeader("Connection", "close");	
			//xmlreqs[pos].xmlhttp.setRequestHeader("Proxy-Connection", "close");
		} else {
			
			////////////
			//
			//debug info
			//
			if (debugProcTime !== false) {
				params += "&debugProcTime=" + debugProcTime;
			}
			xmlreqs[pos].xmlhttp.open("GET",url+"?"+params,true);
			//xmlreqs[pos].xmlhttp.setRequestHeader("Connection", "close");
			//xmlreqs[pos].xmlhttp.setRequestHeader("Pragma", "no-cache");
			//xmlreqs[pos].xmlhttp.setRequestHeader("Cache-Control", "no-cache");
			//xmlreqs[pos].xmlhttp.setRequestHeader("Proxy-Connection", "close");
		}
		xmlreqs[pos].xmlhttp.onreadystatechange = function() {
			if (typeof(xmlhttpChange) != 'undefined') { xmlhttpChange(pos); }
		}
		if (method == 'post') {
			xmlreqs[pos].xmlhttp.send(params);
		} else if (window.XMLHttpRequest) { //Mozilla/Safari/IE7+
			xmlreqs[pos].xmlhttp.send(null);
		} else if (window.ActiveXObject) { //IE6-
			xmlreqs[pos].xmlhttp.send();
		}
		//aaMsg = new Array();
		//aaMsg['ID'] = '';
		//aaMsg['ts'] = currentTimestamp();
		//aaMsg['sender'] = member;
		//aaMsg['msg'] = params + " [" + xmreqsAverage + "]";
		//aaMsg['alert'] = 'n';
		//appendMsg(aaMsg);
		//scrollDown();
	}
}

function xmlreqGET(url) {
	var pos = -1;
	//var xmltimeout = false;
	//var cts = new Date() - 5000; // set timeout for 5 seconds ago
	l = xmlreqs.length;
	for (var i=0; i<l; i++) {
		if (xmlreqs[i].freed == 1) {
			pos = i;
			break;
		//} else if (xmlreqs[i].ts < cts) { //check whether there is an ajax call timeout 
		//	xmltimeout = true;
		}
	}
	//if ((pos == -1 && xmlreqs.length>24) || xmltimeout == true) { //cancels poll if 25 queries currently waiting, or if there's an ajax call timeout
	//	server_slow();
	//	return null;
	//}
	if (pos == -1) { pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1); }
	if (xmlreqs[pos].xmlhttp) {
		xmlreqs[pos].ts = new Date();
		xmlreqs[pos].freed = 0;
		xmlreqs[pos].xmlhttp.open("GET",url,true);
		xmlreqs[pos].xmlhttp.setRequestHeader("Connection", "close");
		xmlreqs[pos].xmlhttp.onreadystatechange = function() {
			if (typeof(xmlhttpChange) != 'undefined') { xmlhttpChange(pos); }
		}
		if (window.XMLHttpRequest) {
			xmlreqs[pos].xmlhttp.send(null);
		} else if (window.ActiveXObject) {
			xmlreqs[pos].xmlhttp.send();
		}
	}
}

function xmlreqPOST(url,data) {
	var pos = -1;
	for (var i=0; i<xmlreqs.length; i++) {
		if (xmlreqs[i].freed == 1) { pos = i; break; }
	}
	if (pos == -1) {
		pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1);
	}
	if (xmlreqs[pos].xmlhttp) {
		xmlreqs[pos].ts = new Date();
		xmlreqs[pos].freed = 0;
		xmlreqs[pos].xmlhttp.open("POST",url,true); xmlreqs[pos].xmlhttp.onreadystatechange = function() {
			if (typeof(xmlhttpChange) != 'undefined') {
				xmlhttpChange(pos);
			}
		}
		xmlreqs[pos].xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlreqs[pos].xmlhttp.send(data);
	}
}

function xmlhttpChange(pos) {
	var currentTime = new Date();
	if (typeof(xmlreqs[pos]) != 'undefined' && xmlreqs[pos].freed == 0 && xmlreqs[pos].xmlhttp.readyState == 4) {
		try {
			if (xmlreqs[pos].xmlhttp.status !== undefined && xmlreqs[pos].xmlhttp.status != 0){
				httpStatus[pos] = xmlreqs[pos].xmlhttp.status;
			} else {
				httpStatus[pos] = 13030;
			}
		}
		catch(e){
			// 13030 is the custom code to indicate the condition -- in Mozilla/FF --
			// when the object's status and statusText properties are
			// unavailable, and a query attempt throws an exception.
			httpStatus[pos] = 13030;
		}
		if (httpStatus[pos] == 13030) {
			handle_error();
		} else if (xmlreqs[pos].xmlhttp.status == 200 || xmlreqs[pos].xmlhttp.status == 304) {
			handle_response(xmlreqs[pos].xmlhttp.responseXML);
		} else {
			handle_error();
		}
		xmlreqs[pos].freed = 1;
		xmlreqs[pos].timeout = currentTime.getTime() + 700; //we wait a few miliseconds before making this connection available for a new call 
		ajaxProcTime(currentTime.getTime() - xmlreqs[pos].ts);
		httpStatus[pos] = false;
	}
}

function handle_response(xml) {	
	for(j = 0; j < xml.firstChild.childNodes.length; j++)	{
		pXml = xml.firstChild.childNodes[j];
		switch (pXml.nodeName) {
			case "f": //friend list update
				callbackFriendlist(pXml.getElementsByTagName("l"));
			break
			case "im": //instant message
				processIMessages(pXml.getElementsByTagName("m"));
			break
			case "cb": //chat message
				processChatMessages(pXml.getElementsByTagName("m"));
				processChatUserList(pXml.getElementsByTagName("u"));
			break
			case "s": //system message
				aMsg = pXml.getElementsByTagName("m")				
				IMsystemMsg(aMsg[0].childNodes[0].firstChild.data, aMsg[0].childNodes[1].firstChild.data, aMsg[0].childNodes[2].firstChild.data);
			break
			case "nm": //new mail
				callbackNewMail(pXml);	
			break
			case "nim": //new instant message
				callbackNewIM(pXml.getElementsByTagName("nims"));
			break
		}
	}
}
