// TODO: Alter all RW_ViewData... messages to use same conventions established by RW_MapFullScreen2
// ie.
// 1. xml element names use lower case only.
// 2. responses only start with <result, <error or <progress
// 3. response <Data... is replaced by <result...
// 4. <error is a response in its own right - not embedded inside <result
// 5. All access is through the AJAX_ functions in this module.


var AJAX_objXmlHttp		= null;
var AJAX_reqCallback		= null;
var AJAX_requestQueue	= null;
var AJAX_savedPostData	= null;	// for debug only

//------------------------------------------------------------------------------
function AJAX_CallServer(url, postData, callbackFn)
{
	return AJAX_CallServer2(url, postData, callbackFn, true);
} // AJAX_CallServer
//------------------------------------------------------------------------------
function AJAX_CallServer2(url, postData, callbackFn, bAsForm)
{
	if (AJAX_ServerIsBusy())
	{
		// we are busy now so save request at end of queue
		var aNewRequest = new AJAX_RequestObject(url, postData, callbackFn);
		if (AJAX_requestQueue == null)
			AJAX_requestQueue = aNewRequest;
		else
		{
			var aRequest = AJAX_requestQueue;
			while (aRequest.nextRequest != null)
				aRequest = aRequest.nextRequest;
			aRequest.nextRequest = aNewRequest;
		}
		// and wait- will be dequeued in AJAX_OnServerStateChange
		return;
	}

	AJAX_objXmlHttp = AJAX_GetXmlHttp();
	if (AJAX_objXmlHttp)
	{
		AJAX_objXmlHttp.onreadystatechange = AJAX_OnServerStateChange;
		AJAX_objXmlHttp.open("POST", url, true);	// true = async
		if (bAsForm)
			AJAX_objXmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		AJAX_objXmlHttp.send(postData);
		AJAX_reqCallback = callbackFn;
		AJAX_savedPostData = postData;	// debugging
		// TODO: can start a timer and call AJAX_objXmlHttp.abort() if we have waited too long
	}
} // AJAX_CallServer2
//------------------------------------------------------------------------------
function AJAX_CallServerSynchronous(url, postData)
{
	return AJAX_CallServerSynchronous2(url, postData, true);
} // AJAX_CallServerSynchronous
//------------------------------------------------------------------------------
function AJAX_CallServerSynchronous2(url, postData, bAsForm)
{
	var objXmlHttpSync = AJAX_GetXmlHttp();
	if (objXmlHttpSync)
	{
		objXmlHttpSync.open("POST", url, false);	// false = sync
		if (bAsForm)
			objXmlHttpSync.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		objXmlHttpSync.send(postData);
		return AJAX_ProcessResponse(objXmlHttpSync);
	}
	return null;
} // AJAX_CallServerSynchronous2
//------------------------------------------------------------------------------
function AJAX_GetXmlHttp()
{
	var x = null;
   if (window.XMLHttpRequest)			// Mozilla, Safari, ...
	{
		x = new XMLHttpRequest();
      if (x.overrideMimeType)
         x.overrideMimeType('text/xml');
   } 
   else if (window.ActiveXObject)	// IE 
   {
		try
		{
			x = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e)
		{
			try
			{
				x = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(e)
			{
			x = null;
			}
		}
	}
	
	return x;
} // AJAX_GetXmlHttp
//------------------------------------------------------------------------------
function AJAX_OnServerStateChange()
{
	if (AJAX_objXmlHttp == null)
		return;
	if (AJAX_objXmlHttp.readyState != 4)
		return;
	if (AJAX_objXmlHttp.status != 200)
	{
		alert ("Callback error: status=" + AJAX_objXmlHttp.status + ": " + AJAX_objXmlHttp.statusText);
		return;
	}
		
	//alert ("Response received");
	//alert (AJAX_objXmlHttp.responseText);
	var oXML = AJAX_ProcessResponse(AJAX_objXmlHttp);
	if (oXML == null)
	{
		// reply contains neither <result... nor <progress... nor <error...
		// so ignore it
		AJAX_objXmlHttp	= null;
		AJAX_reqCallback	= null;
	}
	else
	{
		// alert (oXML.xml);
		AJAX_objXmlHttp	= null;
		var callbackFn = AJAX_reqCallback;
		AJAX_reqCallback	= null;
		callbackFn(oXML);
		oXML			= null;
	}
	
	// Process next queued request, if any.
	if (AJAX_requestQueue != null)
	{
		var aRequest = AJAX_requestQueue;
		AJAX_requestQueue = aRequest.nextRequest;
		AJAX_CallServer(aRequest.url, aRequest.postData, aRequest.callbackFn);
		aRequest = null;
	}
} // AJAX_OnServerStateChange
//------------------------------------------------------------------------------
function AJAX_ProcessResponse(objXmlHttp)
{
	var oXML = objXmlHttp.responseXML;
	// strip off any ASP debug metadata
	// ("real" response, being XML, starts with <?xml...
	var i = objXmlHttp.responseText.indexOf('<result');
	if (i < 0)
		i = objXmlHttp.responseText.indexOf('<progress');
	if (i < 0)
		i = objXmlHttp.responseText.indexOf('<Data');	// returned by RW_ViewData_Svr.asp
	if (i < 0)
		i = objXmlHttp.responseText.indexOf('<error');
	if (i < 0)
	{
		// reply contains neither <result... nor <progress... nor <error... nor <Data...
		// so ignore it
		oXML			= null;
	}
	else
	{
		if (isMoz || isSafari)
		{
			oXML = AJAX_ParseString(objXmlHttp.responseText.substr(i));
		}
		else
		{
			oXML.loadXML (objXmlHttp.responseText.substr(i));
			if (oXML.parseError.errorCode != 0)
			{
				oXML.loadXML ('<error desc="' + oXML.parseError.reason + '"/>');
			}
		}
	}
	return oXML;
} // AJAX_ProcessResponse
//------------------------------------------------------------------------------
function AJAX_RequestObject(url, postData, callbackFn)
{
	this.url				= url;
	this.postData		= postData;
	this.callbackFn	= callbackFn;
	this.nextRequest	= null;
} // AJAX_RequestObject
//------------------------------------------------------------------------------
function AJAX_ServerIsBusy()
{
	return (AJAX_reqCallback != null);
} // AJAX_ServerIsBusy
//------------------------------------------------------------------------------
function AJAX_UrlEncode(s)
{
	var s1 = s;
	s1 = escape(s1);
	// escape() doesnt do '+' chars, so do these explicitly
	s1 = s1.replace(/\+/g,"%2b");
	return s1;
} // AJAX_UrlEncode
//------------------------------------------------------------------------------
function AJAX_GetFormState()
{
	// Retrieve form data, as submit() would do
	
	// But also include items that have IDs but not names.
	// (Most callers should not use this capability, which has been added to support
	//  the ProposalLaunch2.asp page in InsertExpress.)
	var s = '';
	for (var i = 0; i < document.frmMain.elements.length; i++)
	{
		var e		= document.frmMain.elements[i];
		var id	= (e.name.length > 0) ? e.name : e.id;
		var val	= e.value;

		if (id && val)
		{
			var bOutput;
			switch (e.type.toUpperCase())
			{
				case "RADIO":
				case "CHECKBOX":
					bOutput = e.checked;
					break;
				default:
					bOutput = true;
					break;
			}			
			if (bOutput)
			{
				if (s != '')
					s += '&';
				if (window.REQ_UrlEncode)
					s += id + '=' + REQ_UrlEncode(val);
				else
					s += id + '=' + AJAX_UrlEncode(val);
			}
		}
	}
	return s;
} // AJAX_GetFormState
//------------------------------------------------------------------------------
function AJAX_ParseString(str)
{
	// Equivalent of loadxml method in firefox; return xml document
	var oParser = new DOMParser();
	var s = oParser.parseFromString(str, "text/xml");
	return s;
} // AJAX_ParseString
//------------------------------------------------------------------------------
function AJAX_SerializeXML(oNode)
{
	// Equivalent of xml property in firefox; returns xml string
	var oSerializer = new XMLSerializer();
	var s = oSerializer.serializeToString(oNode);
	return s;
} // AJAX_SerializeXML
//------------------------------------------------------------------------------
