/**
 * Ajax object
 *
 * A Javascript Ajax object to handle Ajax communications.
 *
 * @author Wouter Thielen
 * @credits Simon Koster
 *
 **/

var Ajax = {
	m_sUrl : null,
	m_sSection : null,
	m_aData : null,
	m_aRequests : [],
	m_bAsync : true,
	m_aDataListeners : null,
	m_oHandler : null,
	m_bInitialized : false,

	init : function(p_sUrl, p_sSection) {
		if (Ajax.m_bInitialized) return;

		// Create HTTP handler
		l_oHTTPHandler = false;
		/*@cc_on @*/
		/*@if (@_jscript_version >= 5)
		// JScript gives us Conditional compilation, we can cope with old IE versions.
		// and security blocked creation of the objects.
		try {
			l_oHTTPHandler = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (l_oException1) {
			try {
				l_oHTTPHandler = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (l_oException2) {
				l_oHTTPHandler = false;
			}
		}
		@end @*/
		if (!l_oHTTPHandler && typeof XMLHttpRequest!='undefined') {
			l_oHTTPHandler = new XMLHttpRequest();
		}
		this.m_oHandler = l_oHTTPHandler;

		// Initialize variables
		if (p_sSection == null) p_sSection = 'blog';
		this.m_sUrl = p_sUrl;
		this.m_sSection = p_sSection;
		this.m_aDataListeners = new Array();
		this.m_bInitialized = true;
	},

	// Adds a listener
	addDataListener : function(p_sIdentifier, p_fFunc) {
		this.m_aDataListeners[p_sIdentifier] = p_fFunc;
	},

	// Sends the request
	send : function(p_aData) {
		this.m_aRequests.push(p_aData);

		// Filter out previous requests with the same identifier
		var l_aQueued = new Array();
		var l_aRequests = new Array();
		while (l_aData = this.m_aRequests.pop()) {
			if (!l_aQueued[l_aData['identifier']]) {
				l_aQueued[l_aData['identifier']] = true;
				l_aRequests.unshift(l_aData); // Keep the order of the calls
			}
		}
		this.m_aRequests = l_aRequests;

		processQueue();
	},

	isBusy : function() {
		return (this.m_oHandler.readyState > 0 && this.m_oHandler.readyState < 4);
	},

	hasRequests : function() {
		return (this.m_aRequests.length > 0);
	},

	setAsync : function(p_bAsync) {
		this.m_bAsync = p_bAsync;
	}
}

function processQueue() {
	if (Ajax.isBusy()) {
		setTimeout("processQueue()", 100);
		return;
	}

	Ajax.m_aData = Ajax.m_aRequests.shift(); // FIFO principle

	// Open a connection and set headers
	Ajax.m_oHandler.open('POST', Ajax.m_sUrl + '?section=' + Ajax.m_sSection, Ajax.m_bAsync);
	Ajax.m_oHandler.setRequestHeader("Cache-Control", "no-cache");
	Ajax.m_oHandler.setRequestHeader("X_USERAGENT", "BloogAjax");
	Ajax.m_oHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	Ajax.m_oHandler.setRequestHeader("Connection", "close");

	if (Ajax.m_bAsync) {
		// Prepare callback function
		Ajax.m_oHandler.onreadystatechange = function() {
			if (Ajax.m_oHandler.readyState == 4 && (Ajax.m_aData['identifier'] || Ajax.m_aData['callback'])) {
				var l_oObject = eval('(' + Ajax.m_oHandler.responseText + ')');
				if (Ajax.m_aData['identifier']) {
					Ajax.m_aDataListeners[Ajax.m_aData['identifier']](l_oObject);
				}
				if (Ajax.m_aData['callback']) {
					Ajax.m_aData['callback'](l_oObject);
				}
			}
		}
	}

	// Send request
	Ajax.m_oHandler.send('data=' + escape(JSON.encode(Ajax.m_aData)));
	
	if (!Ajax.m_bAsync) {
		if (Ajax.m_aData['identifier']) {
			var l_oObject = eval('(' + Ajax.m_oHandler.responseText + ')');
			if (Ajax.m_aData['identifier']) {
				Ajax.m_aDataListeners[Ajax.m_aData['identifier']](l_oObject);
			}
			if (Ajax.m_aData['callback']) {
				Ajax.m_aData['callback'](l_oObject);
			}
		}
	}

	if (Ajax.hasRequests()) processQueue();
}
