function Ajax () { 
}

Ajax.createRequestObject = function Ajax_createRequestObject () {
	var req = false;

	var browser = navigator.appName;

	if (window.XMLHttpRequest) {
		try {
			req = new XMLHttpRequest();
		} catch(e) {
			req = false;
		}
	} else if (window.ActiveXObject) {
		try {
			req = new ActiveXObject("Microsoft.XMLHTTP");
		} catch(e) {
			req = false;
		}
	}

	return req;
}

Ajax.http = Ajax.createRequestObject();
Ajax.output = null;
Ajax.busy = false;
Ajax.elementsToUpdate = new Array();
Ajax.timeOuts = new Array();
Ajax.tokenSent = null;
Ajax.totalNumberOfRequests = 0;

Ajax.addElementToUpdate = function Ajax_addElementToUpdate (el_id) {
	Ajax.elementsToUpdate[elementsToUpdate.length] = el_id;
}

Ajax.token_counters = new Array();
Ajax.number_of_retries = 4;

Ajax.canRetry = function Ajax_canRetry (token) {
	if (Ajax.token_counters[token] == null) { 
		Ajax.flushCounter(token); 
	}

	return (Ajax.token_counters[token] < Ajax.number_of_retries) ? 1 : 0;
}

Ajax.flushCounter = function Ajax_flushCounter (token) {
	Ajax.token_counters[token] = 0;
}

Ajax.flushOutput = function Ajax_flushOutput () {
	Ajax.output = null;
}

Ajax.setOutput = function Ajax_setOutput (output) {
	Ajax.output = output;
}

Ajax.registerRetry = function Ajax_registerRetry (token) {
	Ajax.token_counters[token]++;
}

Ajax.setRequestBusy = function Ajax_setRequestBusy (tf) {
	if (tf == false) {
		Ajax.tokenSent = null;
	}

	Ajax.busy = tf;
}

Ajax.isRequestBusy = function Ajax_isRequestBusy () {
	return (Ajax.busy != false) ? 1 : 0;
}

Ajax.parseResponse = function Ajax_parseResponse(token, action, func, data) {
	try {
		var error = null;

		if (Ajax.http.readyState && Ajax.http.readyState == 4) {
			if (Ajax.http.status == 200) {
				Ajax.readResponse(func);
				Ajax.setRequestBusy(false);
   			Ajax.timeOuts[token] = null;

			} else {
				Logger.log("Ajax.http.status is not 200, it's " + Ajax.http.status);
				error = 1;
			}
		}

		if (error == 1) {
			Logger.log("http error has accured, let's retry");

			if (Ajax.canRetry(token)) {
				Ajax.registerRetry(token);
				Ajax.http.abort();
				Ajax.setRequestBusy(false);
   			Ajax.timeOuts[token] = null;
				Ajax.sendRequest(token, action, func, data);
			} else {
				Ajax.readResponseError(token, func);
			}
		}
	} catch (e) {
		Logger.log("PARSER error occured! " + e);

		if (Ajax.canRetry(token)) {
			Ajax.registerRetry(token);
			Ajax.http.abort();
			Ajax.http = Ajax.createRequestObject();
			Ajax.setRequestBusy(false);
			Ajax.timeOuts[token] = null;
			Ajax.sendRequest(token, action, func, data);
		} else { 
			Ajax.readResponseError(token,func);
		}
	}
}

Ajax.sendRequest = function Ajax_sendRequest(token, action, func, data, caller) {
/*	Ajax.totalNumberOfRequests++;

	if (Ajax.totalNumberOfRequests > 10) {
		return Logger.log('AJAX - req>10!');//XXX
	}
*/

	if (Ajax.timeOuts[token] != null && Ajax.timeOuts[token] > 10) {
		Logger.log("too many requests are waiting with token " + token);
		return;
	}

	try {
		if (!Ajax.isRequestBusy()) {
			var data_to_send = "";

			if (typeof(data) == 'string') {
				data_to_send = Core.escape(data);
			} else if (typeof(data) == 'object') {
				for (var i in data) {
					data_to_send += i + "=" + Core.escape(data[i]) + "|";
				}
			} else {
				Logger.log('wrong data type in sendRequest: ' + typeof(data));
			}

			Ajax.setRequestBusy('true');
			var get_str = '?rnd=' + Math.random()*4 + '&token=' + token + '&cmd=' + action + '&data=' + data_to_send;
			Ajax.http.open('get', get_str);
			Ajax.flushOutput();

			Ajax.http.onreadystatechange = function () {
            Logger.log(token);
				Ajax.parseResponse(token, action, func, data);
			};

			Ajax.http.send(null);
			Ajax.tokenSent = token;
			Ajax.timeOuts[token] = null;
		} else {
			Logger.log("Ajax is busy! Queueing the function");

			if (Ajax.tokenSent == token) {
				Logger.log("the same token requested, while we wait for the response");
				Ajax.http.abort();
				Ajax.http = Ajax.createRequestObject();
				Ajax.setRequestBusy(false);
			}

			if (Ajax.timeOuts[token] == null) {
				Ajax.timeOuts[token] = 1;
			} else {
            if (caller == null || caller != 'retry') {
				   Ajax.timeOuts[token] = Ajax.timeOuts[token] + 1;
            }
			}
	
			window.setTimeout(function () {
				Ajax.sendRequest(token, action, func, data, 'retry')
			}, 200);
		}
	} catch (e) {
		Logger.log("XMLHttpRequest error occured: " +e);
	}
}

Ajax.readResponseError = function Ajax_readResponseError(token, func) {
	Ajax.setRequestBusy(false);
	Ajax.flushCounter(token);
	var output_array = new Array();
	output_array["token"] = "error";
	eval(func + "(output_array)");
}

Ajax.checkToken = function Ajax_checkToken(token) {
	return (token == null || token == '' || Ajax.http.responseText == null || token == 'error') ? 0 : 1;
}

Ajax.checkData = function Ajax_checkData(data) {
	return (data == '' || data == null || data == ' ' || data == '\n')? 0 : 1;
}

Ajax.readResponse = function Ajax_readResponse(func) {
/*	Ajax.totalNumberOfRequests--;
	if (Ajax.totalNumberOfRequests<0) {
		Ajax.totalNumberOfRequests = 0;
	}	

Logger.log('RESP num of req left:' + Ajax.totalNumberOfRequests);
*/
	if (Ajax.responseOK()) {
		//var response = Ajax.http.responseText.split('|');
		
		var output = new Object();
		output.token = Ajax.http.responseText.substr(0, Ajax.http.responseText.indexOf("|"));
		output.data  = Ajax.http.responseText.substr(Ajax.http.responseText.indexOf("|")+1);;

		var content_type = Ajax.http.getResponseHeader("Content-Type");

		if (content_type != null && content_type == "text/plain" && output.data != null && output.data.indexOf("=") > -1) {
			var pairs = output.data.split('|');

			var responseParams = new Object();

			for (var y=0; y<pairs.length; y++) {
				var pair = pairs[y].split('=');
				responseParams[pair[0]] = Core.unescape(pair[1]);
			}

			output.params = responseParams;
		}

		Ajax.setRequestBusy(false);

		if (!Ajax.checkToken(output.token) ) {
			Ajax.readResponseError(output.token);
			output.token = "error";
		}

//		Logger.log("returning token: " + output["token"]); 
//		Logger.log("returning data: " + output["data"]); 
//		Logger.log('BOOL=' + (output.params == null));
		if (Core.isFunction(func)) {
			eval("func(output)");
		} else {
			eval(func+"(output)");
		}
	} else {
		Logger.log("Ajax.reponseOK() false");
	}
}

Ajax.responseOK = function Ajax_responseOK () {
	return (Ajax.http != null && Ajax.http.readyState == 4 && Ajax.http.status == 200 && (Ajax.http.responseText.indexOf('error|') == -1)) ? 1 : 0;
}


Ajax.updateElement = function Ajax_updateElement (el_id, action) { 
	if (Ajax.busy == false) {
		Ajax.busy = true;
		Ajax.http.open('get', '?rnd=' + Math.random()*4 + '&el_id=' + el_id + '&cmd=' + action);
		Ajax.http.onreadystatechange = Ajax.doUpdate;
		Ajax.http.send(null);
	} else {
		window.setTimeout("updateElement('" + el_id + "', '" + action + "')", 10);
	}
}

Ajax.updateGroup = function Ajax_updateGroup (prefix, action) { 
	for (var i=0; i<Ajax.elementsToUpdate.length; i++) { 
		if (Ajax.elementsToUpdate[i].substr(0, prefix.length) == prefix) {
			Ajax.updateElement(elementsToUpdate[i], action);
		}
	}
}

Ajax.doUpdate = function Ajax_doUpdate  () {
    if (Ajax.http.readyState == 4) {
        var response = Ajax.http.responseText;
        var update = new Array();

        if (response.indexOf('|') != -1) {
            update = response.split('|'); 
            var el_id = update.shift();
            var text = update.join("|");
            Core.setText(el_id, text);
        } else {
		if(Ajax.debug == 1) Logger.log('wrong response received: ' + response);
	}

        Ajax.busy = false;
    }
}
