//
// Ajax* related JavaScript code - this should be included on the front end and backend.
//
// * - Strictly speaking this isn't 'Ajax' as we don't do the 'X'.
//
// NB: This requires several CSS definitions (stored in /css/extras.css) for the displayAjaxFailure output to display correctly.
//     Additionally, this requires a /images/cms/error_dialog.jpg file (as referenced within the CSS definitions).
//
// v1.12 - Added 'Missing destination element reference' error message.
// v1.11 - Update showFullDebugResponse to apply to eval data.
// v1.10 - Added 'ignoring malformed response' debug message.
// v1.09 - Moved timeout setup prior to request firing in sendRequest.
// v1.08 - Added error display to the exception handling in sendRequest and handleRequest, tweaked return value of createRequestObject.
// v1.07 - Added a timeout handler for each sendRequest.
// v1.06 - Added HTTP response status verification.
// v1.05 - Attempt to use Msxml2.XMLHTTP prior to (the depreciated) Microsoft.XMLHTTP if we can't use a vanilla XMLHttpRequest.
// v1.04 - Minor tweak to add a typeof check on the creation of the request object.
//		 - Added additional exception handler around the eval within handleResponse.
// v1.03 - Adds a timeout detector and failure message, etc.
// v1.02 - Fixes bug in wait states running under Firefox.
// v1.01 - Includes support for multiple simultaneous requests.
//

var showFullDebugResponse = false;																// Whether or not we show the full return data...
var responseTimeout = 30;																		// The maximum response timeout in seconds...
var readyStateStrings = new Array('Uninitialized', 'Open', 'Sent', 'Receiving', 'Loaded');		// The textual version of the ready states...
var httpSlots = new Array;																		// Our global request objects...
var slotUsage = new Array;																		// Our global response statuses...
var slotTimeouts = new Array;																	// Our global slot response timeouts...
var slotTimeoutIDs = new Array;																	// Our global slot response timeouts IDs...
var failState = false;																			// Our global failState...


// Used to display the failure message...
function displayAjaxFailure(errorString) {
	if(!failState) {
		failState = true;
		pageSize = getPageSize();
		scrollSize = getPageScroll();
		
		// Set up our overlay...
		createElement('ajaxoverlay', 'div', 'ajaxoverlay');
		overlayDiv = document.getElementById('ajaxoverlay');
		overlayDiv.style.height = pageSize[1]+'px';

		// Set up our message...
		createElement('ajaxmodalmessage', 'div', 'ajaxmodalmessage');
		messageDiv = document.getElementById('ajaxmodalmessage');
		messageDiv.style.top = (100+scrollSize[1])+'px';
		messageDiv.style.left = Math.floor((pageSize[0]/2)-200)+'px';
		tempHTML  = '<div style="padding:16px;padding-left:70px;">';
		tempHTML += '<h1>A problem has occured</h1>';
		tempHTML += '<p>Sorry, but a problem occured whilst trying to process your selection - please ';
		tempHTML += '<span id="reload" onclick="window.location.reload();">reload this page</span> to try again.</p>';
		tempHTML += '<p>If this problem persists, please contact us quoting the error "<strong class="amber">'+errorString+'</strong>".</p>';
		tempHTML += '</div>';
		messageDiv.innerHTML = tempHTML;

		hideElements('select');					// Hide the selects...
	
		// Finally, we'll show the divs...
		showDiv('ajaxoverlay');
		showDiv('ajaxmodalmessage');
	}
}


// Used to initialise the global request object...
function createRequestObject() {

	var requestObject = null;
	
	if (typeof XMLHttpRequest != "undefined") return (requestObject = new XMLHttpRequest());
	else if (window.ActiveXObject) {
		
		// We'll try the Microsoft ActiveX versions (best first)...
		var activeXVersions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
		
		for(var loop=0; loop<activeXVersions.length; loop++) {
			try {
				requestObject = new ActiveXObject(activeXVersions[loop]);
				return requestObject;
			} catch (ourEx) {
				// We don't want to do anything here...
			}
		}
	}
		
	displayAjaxFailure("Couldn't create request object");
	
	return false;
}



// Used to send the HTTP request...
function sendRequest(refName, url) {
	
	// We only allow one concurrent request for each reference...
	if(!slotUsage[refName] || slotUsage[refName] == false) {
		if(httpSlots[refName] = createRequestObject()) {
			try {
				// Set defaults...
				var tempDate = new Date;
				slotUsage[refName] = true;
				slotTimeouts[refName] = tempDate.getTime() + (responseTimeout * 1000);
				
				// Add a random timestamp to the URL to prevent browser caching...
				url += (url.indexOf('?') != -1 ? '&' : '?')+slotTimeouts[refName]+'='+slotTimeouts[refName];

				// Create a connection timeout...
				slotTimeoutIDs[refName] = setTimeout( function() { httpSlots[refName].abort; displayAjaxFailure("Response timed out (1)"); }, responseTimeout * 1000);		

				// Fire the request...
				httpSlots[refName].open('get', url, true);
				httpSlots[refName].onreadystatechange = function() { handleResponse(refName); }		// Inline as we can't call with an arg...
				httpSlots[refName].send(null);
			}
			catch(ourEx) { 
				window.status = ourEx;
				displayAjaxFailure("Unable to create HTTP request - "+ourEx);
			}
		}
	}
}


// Used to process the request response...
function handleResponse(refName) {

	if(!failState) {
		// Check our slot timeout...
		var tempDate = new Date;
		debugString  = 'handleResponse (<strong>'+refName+'</strong>) - readyState: <strong>'+readyStateStrings[httpSlots[refName].readyState]+'</strong>, ';
		debugString += 'timer: <strong>'+(Math.round((slotTimeouts[refName]-tempDate.getTime()) / 1000))+'</strong>...';
		debug(debugString);
		
		if(tempDate.getTime() > slotTimeouts[refName]) {
			httpSlots[refName] = null;
			slotTimeouts[refName] += tempDate.getTime() + (responseTimeout * 1000);
			displayAjaxFailure("Response timed out (2)");
		}
	
		//try {
			if(httpSlots[refName].readyState == 4) {
			
				clearTimeout(slotTimeoutIDs[refName]);			// Prevent the timeout from being called...
				
				// Was the response valid?
				if(httpSlots[refName].status == 200) { 
				
					slotUsage[refName] = false;
					var response = httpSlots[refName].responseText;
					var chunk = new Array();
					
					if(response.length) {
						if(response.indexOf('|') != -1) {
							chunk = response.split('|');
							if(chunk[0] && chunk[1]) {
								// Ensure there's a destination to insert into...
								if(document.getElementById(chunk[0])) document.getElementById(chunk[0]).innerHTML = chunk[1];
								else displayAjaxFailure('Missing destination element reference \''+chunk[0]+'\'</strong>...');
							}
						
							// Is there any Javascript to be evaled?
							if(chunk.length >2) {
								try {
									eval(chunk[2]);
								}
								catch(ourEx) {
									debug('handleResponse (<strong>'+refName+'</strong>) - Error \''+ourEx+'\' evaluating JavaScript code \''+chunk[2]+'\'');
								}
							}
						
							// *** DEBUG ***
							responseData = showFullDebugResponse ? (chunk[1] ? '"'+chunk[1]+'"' : 'N/A') : chunk[1].length+' byte(s)';
							evalData = chunk[2] ? (showFullDebugResponse ? (chunk[2] ? '"'+chunk[2]+'"' : 'N/A') : chunk[2].length+' byte(s)') : '';
							debugString  = 'handleResponse (<strong>'+refName+'</strong>) - status: <strong>'+httpSlots[refName].statusText+'</strong> - ';
							debugString += 'dest: "<strong>'+chunk[0]+'</strong>" - data: <strong>'+responseData+'</strong> - ';
							debugString += 'eval: <strong>'+evalData+'</strong>...';
							debug(debugString);
						}
						else debug('handleResponse (<strong>'+refName+'</strong>) - <strong class="red">Ignoring malformed response</strong>...');
					}
					else displayAjaxFailure("Received zero length response (Status "+httpSlots[refName].status+" - "+httpSlots[refName].statusText+")");
				}
				else displayAjaxFailure("Received bad server response (Status "+httpSlots[refName].status+" - "+httpSlots[refName].statusText+")");
			}
			
		//}
		
		/*catch(ourEx) {
			window.status = ourEx;
			displayAjaxFailure("Unknown error during handleResponse phase (Status "+httpSlots[refName].status+" - "+httpSlots[refName].statusText+")");
		}*/
	}
}
