
function NaosAjax(requests, domForms, callbackCreateData)
{
	NaosDebug.debug("[NaosAjax]: Preparing request.");
		
	// transform to vanilla object
	requests = NaosTools.toVanillaObject(requests);
	
	// generate url from requests and status...
	var url = naosConfig.application.base_url+'.ajax/'+naosStatus.application.locale+'/'
		+naosStatus.application.menuItem;
		
	// ... and generate xml request
	var xml = zXmlDom.createDocument();
	
	var xml_request_ajax = xml.createElement('ajax');
	
	var xml_request = xml.createElement('request');
	xml_request.appendChild(xml_request_ajax);
	
	xml.appendChild(xml_request);
	
	// update url and xml request with current status
	var views = naosConfig.layout.views.split(',');
	for(var i=0; i<views.length; ++i)
	{
		var viewStatus = null;
		
		// get current status and update with request
		if(naosStatus.layout[views[i]] != undefined)
			viewStatus = naosStatus.layout[views[i]];
			
		if(requests[views[i]] != undefined)
			viewStatus = requests[views[i]];
			
		if(viewStatus == null)
			continue;
		
		// update url
		url += '//'+views[i]+'/'+viewStatus.node+'/'+viewStatus.module+'/'+viewStatus.controller+'/'+
			viewStatus.action;
		
		for(var j in viewStatus.parameter) {
			url += '/'+j+'/'+viewStatus.parameter[j];
		}
	}
	
	for(var i in requests)
	{
		// update xml request
		var xml_request_ajax_view = xml.createElement('view');
		xml_request_ajax_view.setAttribute('id', i);
		xml_request_ajax.appendChild(xml_request_ajax_view);
	}
	
	// append form data to xml request
	for(var i=0; i < domForms.length; ++i)
	{
		var xml_request_ajax_form = xml.createElement('form');
		xml_request_ajax_form.setAttribute('id', domForms[i].name);
		xml_request_ajax_form.setAttribute('items', domForms[i].elements[domForms[i].name+':items'].value);
		xml_request_ajax_form.setAttribute('titles', domForms[i].elements[domForms[i].name+':titles'].value);
		
		for(var j=0; j < domForms[i].elements.length; ++j)
		{
			if(domForms[i].elements[j].name == domForms[i].name+':items' || domForms[i].elements[j].name == domForms[i].name+':titles')
				continue;
				
			if((domForms[i].elements[j].type == 'checkbox' || domForms[i].elements[j].type == 'radio') && domForms[i].elements[j].checked == false)
				continue;
				
			var xml_request_ajax_form_item = xml.createElement('item');
			xml_request_ajax_form_item.setAttribute('id', domForms[i].elements[j].name);
			xml_request_ajax_form_item.appendChild(xml.createTextNode(domForms[i].elements[j].value));
			
			xml_request_ajax_form.appendChild(xml_request_ajax_form_item);
		}
		
		xml_request_ajax.appendChild(xml_request_ajax_form);
	}
	
	// append additional data to xml request
	if(callbackCreateData != null)
		callbackCreateData(xml, xml_request);
	
	// set member variables
	this.requests = requests;
	this.url = url;
	this.xmlrequest = xml;
		
	// create ajax callback functions
	this.callbackOk = function(ajax) {
		
		// display debug message
		NaosDebug.debug("[NaosAjax]: Response received.\nXML: "+
			new zXMLSerializer().serializeToString(ajax.responseXML));
	
		// update application state
		var xml_state = zXPath.selectSingleNode(ajax.responseXML, '/response/ajax/state');
		naosStatus = NaosTools.fromJSON(xml_state.textContent?xml_state.textContent:xml_state.text);
		
		// update view output
		var xml_views = zXPath.selectNodes(ajax.responseXML, '/response/ajax/view');
		for(var k=0; k < xml_views.length; ++k)
		{
			Naos.updateViewContent(xml_views[k].getAttribute('id'), xml_views[k].textContent?xml_views[k].textContent:xml_views[k].text);
			NaosHandler.viewUpdateNotifier(xml_views[k].getAttribute('id'), xml_views[k].textContent?xml_views[k].textContent:xml_views[k].text);
		}
		
		// perform queued operations
		var xml_queuedOperations = zXPath.selectSingleNode(ajax.responseXML, '/response/ajax/queuedOperations');
		var queuedOperations = NaosTools.fromJSON(xml_queuedOperations.textContent?xml_queuedOperations.textContent:xml_queuedOperations.text);
		
		// dialog operations
		for(qopsModule in queuedOperations['dialog'])
		{
			for(qopsDialog in queuedOperations['dialog'][qopsModule])
			{
				if(queuedOperations['dialog'][qopsModule][qopsDialog]['operation'] == 'open')
				{
					NaosDialog.openDialog(qopsModule, qopsDialog,
						queuedOperations['dialog'][qopsModule][qopsDialog]['data']['type'],
						queuedOperations['dialog'][qopsModule][qopsDialog]['data']['position'],
						queuedOperations['dialog'][qopsModule][qopsDialog]['data']['output']);
				}
				else if(queuedOperations['dialog'][qopsModule][qopsDialog]['operation'] == 'close')
				{
					NaosDialog.closeDialog(qopsModule, qopsDialog);
				}
			}
		}
		
		// custom operations
		for(qopsCustomKey in queuedOperations['custom'])
		{
			
			NaosHandler.customOperation(queuedOperations['custom'][qopsCustomKey]['module'], queuedOperations['custom'][qopsCustomKey]['type'], queuedOperations['custom'][qopsCustomKey]['data']);
			
		}
		
		NaosAjax.finishRequest(this);
		
	}.bind(this);
	
	this.callbackError = function(ajax) {
		
		// display debug message
		NaosDebug.debug("[NaosAjax]: Request failed.\nText: "+
			ajax.responseText);
		
		// remove request from queue
		NaosAjax.finishRequest(this);
		
	}.bind(this);
	
	this.callbackDebug = function(ajax) {
		
		// display debug message
		NaosDebug.debug("[NaosAjax]: Request completed.\nText: "+
			ajax.responseText);
			
	}.bind(this);
	
	this.send = function () {
		
		NaosDebug.debug("[NaosAjax]: Queuing request.");
		
		NaosAjax.activateRequest(this);
	}.bind(this);
	
	this._send = function () {
		// display hour glass
		// '<img src="'+naosConfig.application.base_url+'.resources/naos/images/spinner.gif"/>'
		
		// display debug message
		NaosDebug.debug("[NaosAjax]: Send request.\nURL: "+this.url+"\nXML: "+
			new zXMLSerializer().serializeToString(this.xmlrequest));
		
		// send request
		new Ajax.Request(this.url, {method: 'post', onSuccess: this.callbackOk,
			onFailure: this.callbackError, postBody: this.xmlrequest, contentType: 'text/xml',
			encoding: 'UTF-8', evalJSON: false, evalJS: false, asynchronous: true,
			parameters: '',	onComplete: this.callbackDebug
			});
	}.bind(this);
}

NaosAjax.requestQueue = new Array();

NaosAjax.lastGuiEffect = null;

NaosAjax.cancelLastGuiEffect = function()
{
	if(NaosAjax.lastGuiEffect)
	{
		if(NaosAjax.lastGuiEffect.state == 'running')
			NaosAjax.lastGuiEffect.cancel();
		NaosAjax.lastGuiEffect = null;
	}
}

NaosAjax.activateRequest = function (naosajax) {
	NaosAjax.requestQueue.push(naosajax);
	
	NaosDebug.debug("[NaosAjax]: Request queue count is: "+NaosAjax.requestQueue.length);
	
	if(NaosAjax.requestQueue.length == 1)
	{
		// display hour glass
		if(!document.getElementById('naos_hourglass'))
		{
			var blockingElement = document.createElement('div');
			blockingElement.setAttribute('id', 'naos_hourglass');
			blockingElement.style.display = 'none';
			blockingElement.style.position = 'absolute';
			blockingElement.style.left = 0;
			blockingElement.style.top = 0;
			blockingElement.style.width = ''+document.viewport.getDimensions().width+'px';
			blockingElement.style.height = ''+document.viewport.getDimensions().height+'px';
			//blockingElement.style.background = 'white';
			
			blockingElement.innerHTML = '<table style="width: '+blockingElement.style.width+'; height: '+blockingElement.style.height+';"><tr><td style="vertical-align: middle; text-align: center;"><img src="'+naosConfig.application.base_url+'.resources/naos/images/spinner.gif"/></td></tr></table>';
			
			document.getElementsByTagName("body")[0].appendChild(blockingElement);
		}
		
		NaosAjax.cancelLastGuiEffect();
		NaosAjax.lastGuiEffect = $('naos_hourglass').appear({ duration: 0.5 });
		
		NaosAjax.requestQueue[0]._send();
	}
}

NaosAjax.finishRequest = function (naosajax) {
	for(var i=0; i<NaosAjax.requestQueue.length; ++i)
	{
		if(NaosAjax.requestQueue[i] == naosajax)
		{
			NaosAjax.requestQueue.splice(i, 1);
			break;
		}
	}
	
	if(NaosAjax.requestQueue.length >= 1)
	{
		NaosAjax.requestQueue[0]._send();
	}
	else
	{
		// hide hour glass
		NaosAjax.cancelLastGuiEffect();
		NaosAjax.lastGuiEffect = $('naos_hourglass').fade({ duration: 0.1 });
	}
}
