/**************************************

            AJAX library
       (c) Jānis Timma, 2007

**************************************/

String.prototype.deamp = function(){
	var s = this.replace(/(&)/g, '%26');
	return s.replace(/(\+)/g, '%2b');
}

function XMLReqElement(xmlhttp, params, url, bparams, type, count) {
	this.xmlhttp = xmlhttp;
	this.params = params;
	this.retryurl = url;
	this.retryparameters = bparams;
	this.retrytype = type;
	this.retrycount = count;
}

function StatusIndicator(elementid) {
	this.status = 0;
	this.statuselement = document.getElementById(elementid);
	this.addQueue = function () {
		this.status++;
		if (this.statuselement) this.statuselement.innerHTML = '<img src="images/wait.gif" align="absmiddle"/>';
	}
	this.removeQueue = function () {
		this.status--;
		if (this.status < 1 && this.statuselement) this.statuselement.innerHTML = '&nbsp;';
		if (this.status < 0) this.status = 0;
	}
}

function AJAX() {
	this.xmlreqs = Array();
	this.statusindicator = null;
	this.debug = null;
	this.readyStateMessage = Array('Uninitialized', 'Initializing connection', 'Starting download', 'Downloading', 'Request completed');
	this.log = function(txt) {
		if (this.debug) {
			this.debug.innerHTML += txt+'<br/>';
			this.debug.scrollTop = this.debug.scrollHeight;
		}
	}
	/*
		AJAX.setStatusIndicator(elementid)
			String elementid - DOM element which support innerHTML ID attribute
		set status display element
	*/
	this.setStatusIndicator = function(elementid) {
		if (this.statusindicator && this.statusindicator.statuselement)
			this.statusindicator.statuselement.innerHTML = '';
		this.statusindicator = new StatusIndicator(elementid);
	}
	/*
		AJAX.responseHandler()
		parses AJAX response
	*/
	this.responseHandler = function(parent) {
		for (var i=0; i < parent.xmlreqs.length; i++) {
			parent.log('['+i+'] '+this.readyStateMessage[parent.xmlreqs[i].xmlhttp.readyState]+' '+(parent.xmlreqs[i].xmlhttp.readyState > 3?' HTTP #'+parent.xmlreqs[i].xmlhttp.status:''));
			if (parent.xmlreqs[i].xmlhttp.readyState == 4) {
				if (parent.xmlreqs[i].xmlhttp.status == 200) {//HTTP 200 OK && rq completed
					parent.log('['+i+'] Removed from queue');
					if (parent.statusindicator) parent.statusindicator.removeQueue();
					if (parent.xmlreqs[i].params != null) {
						switch (parent.xmlreqs[i].params.type) {
							case 'alert'://alert response if not empty
								if (parent.xmlreqs[i].xmlhttp.responseText!='') alert(parent.xmlreqs[i].xmlhttp.responseText);
								break;
							case 'refresh'://refresh container innerHTML
								if (!parent.xmlreqs[i].params.containerId) break;
								var container = document.getElementById(parent.xmlreqs[i].params.containerId);
								if (container) container.innerHTML = parent.xmlreqs[i].xmlhttp.responseText;
								break;
						}
						if (parent.xmlreqs[i].params.callback) {//if callback function is defined then call it
							parent.xmlreqs[i].params.responseText = parent.xmlreqs[i].xmlhttp.responseText;
							parent.xmlreqs[i].params.callback(parent.xmlreqs[i].params);
						}
					}
					parent.xmlreqs.splice(i, 1);
				} else if (parent.xmlreqs[i].xmlhttp.status > 12000) {
					parent.log('ERROR-Retry#'+parent.xmlreqs[i].retrycount+' ['+i+'] = '+parent.xmlreqs[i].xmlhttp.status);
					if (parent.statusindicator) parent.statusindicator.removeQueue();
/*					if (parent.xmlreqs[i].retrycount < 3) {
						parent.retryurl = parent.xmlreqs[i].retryurl;
						parent.retryparameters = parent.xmlreqs[i].retryparameters;
						parent.params = parent.xmlreqs[i].params;
						parent.retrytype = parent.xmlreqs[i].retrytype;
						parent.retrycount = parent.xmlreqs[i].retrycount;
						this.retry = function(what) {
							clearTimeout(what.parent.interval);
							what.parent.send(what.parent.retryurl, what.parent.retryparameters, what.parent.params, what.parent.retrytype, what.parent.retrycount + 1);
						}
						var me = this;
						parent.interval = setTimeout(function(){me.retry(me);}, 300);*/
//					} else alert('Kļūda savienojumā, mēģiniet vēlreiz!');
					alert('Radās kļūda savienojumā, mēģiniet vēlreiz!');
					parent.xmlreqs.splice(i, 1);
				}
			}
		}
	}
//	this.responseHandler._parent = this; //FF fix - in responseHandler <this> turns out to be function responseHandler..
	/*
		AJAX.send(uri, parameters, extraparameters[, requesttype])
			String uri - POST uri
			Object parameters - POST parameters in type {key1: value, key2: value}
			Object extraparameters - extra parameters {key1: value, key2: value}
				type:
					alert => after response alert response text
					refresh => after response change element by ID(containerId).innerHTML to response text
					callback => after response callfunction callback(extraparameters) with extraparameters.responseText set to response text
			String requesttype - (optional) 'POST' or 'GET' request type, default is 'POST'
		sends AJAX request
	*/
	this.send = function(uri, parametersarray, extraparameters, requesttype, retry) {
		var retrycnt;
		if (!retry) retrycnt = 1; else retrycnt = retry;
		var parameters = Array();
		for (var key in parametersarray)
			parameters.push(key + '=' + encodeURI((parametersarray[key] + '')).deamp());
		parameters = parameters.join('&');
//		alert(parameters);
		var xmlhttp=false;
		try { xmlhttp = new XMLHttpRequest(); }
		catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
		catch (e) { try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
		catch (e) { xmlhttp = false; }}}
		if (xmlhttp) {
			this.xmlreqs.push(new XMLReqElement(xmlhttp, extraparameters, uri, parametersarray, requesttype, retrycnt));
//			xmlhttp._parent = this;
			var me = this;
			xmlhttp.onreadystatechange = function() {me.responseHandler(me);}
			if (this.statusindicator) this.statusindicator.addQueue();
			if (requesttype == null || requesttype == 'POST') {//POST request
				xmlhttp.open('POST', uri, true);
				xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				xmlhttp.setRequestHeader("Content-length", parameters.length);
				xmlhttp.setRequestHeader("Connection", "close");
			} else {//GET request
				xmlhttp.open("GET", uri+'?'+parameters, true);
			}
//			alert('send:'+xmlhttp.send(parameters));
			xmlhttp.send(parameters);
			this.log('['+(this.xmlreqs.length-1)+'] Request sent');
			return true;
		} else return false;
	}
	
	/*
		AJAX.send(form, parameters):object
			Object form - form to serialize
			Object parameters - extra parameters in type {key1: value, key2: value}
			
		Return value: oject with keys containing form data
	*/
	this.serializeForm = function(form, parameters) {
		var allelements = new Array(); var tmp;
		var childs = form.getElementsByTagName('INPUT');
		if (childs && childs.length) for (var t = 0; t < childs.length; t++) allelements.push(childs[t]);
		var childs = form.getElementsByTagName('TEXTAREA');
		if (childs && childs.length) for (var t = 0; t < childs.length; t++) allelements.push(childs[t]);
		var childs = form.getElementsByTagName('SELECT');
		if (childs && childs.length) for (var t = 0; t < childs.length; t++) allelements.push(childs[t]);
		var childs = form.getElementsByTagName('BUTTON');
		if (childs && childs.length) for (var t = 0; t < childs.length; t++) allelements.push(childs[t]);
		var values = {};
		for (var i = 0; i < allelements.length; i++) {
			switch (allelements[i].type) {
				case 'radio':
					if (allelements[i].checked)
						values[allelements[i].name] = allelements[i].value;
					break;
				case 'checkbox':
					values[allelements[i].name] = allelements[i].checked;
					break;
				case 'submit':
				case 'button':
				case 'text':
				case 'hidden':
				case 'textarea':
				case 'select-one':
					values[allelements[i].name] = allelements[i].value;
					break;
				default:
					alert(allelements[i].type);
					break;
			}
		}
		if (parameters) for (var key in parameters) values[key] = parameters[key];
//		for (var key in values) alert('S: '+key+':'+values[key])
		return values;
	}
}
