/////////////////////// AJAX related functions //////////////////////

// Initialize XML
// TODO: see what we can move to a global, one-time init
function fnLoadXML(xString)
{
	if (typeof document.implementation.createDocument!="undefined")
  	{
  		if (document.implementation.createDocument)
  		{
	  		// With Mozilla, we create DOMParser instance
	  		var parser = new DOMParser();
	  		xdoc = parser.parseFromString(xString, "text/xml");
	  		xdoc.normalize();
		}
  	}
  	else if (window.ActiveXObject)
	{
		// With IE, we create new XML document using ActiveX and fn loadXML as DOM parser.
		// Free threaded means only one thread will be able to access the XML objects at a time, which is what we want for thread safety
		//xdoc = new ActiveXObject("Microsoft.FreeThreadedXMLDOM");
		xdoc = new ActiveXObject("Microsoft.XMLDOM")
		xdoc.async="false";
		xdoc.loadXML(xString);
	}
}

function fnIncReqArray()
{
   	g_req_at++;
	if (g_req_at>REQ_ARRAY_MAX-1)
		g_req_at = 0;
	return g_req_at;
}

// This function is from from JavaScript & DHTML Cookbook by Danny Goodman (publisher = O'Reilly) chp 14.8
// License: http://www.oreilly.com/pub/a/oreilly/ask_tim/2001/codepolicy.html
// convert XML data into JavaScript array of JavaScript objects
// Dan Burke: I've modified this function to make it more robust
function fnXML2JS(xmlDoc, containerTag)
{
    var output = new Array();
    var tagData = xmlDoc.getElementsByTagName(containerTag);
    if (null == tagData)
    	return output;
    var rawData = tagData[0];
    if (null == rawData)
    	return output;
    var i, j, oneRecord, oneObject;

   	for (i = 0; i < rawData.childNodes.length; i++)
   	{
        if (rawData.childNodes[i].nodeType == 1)
        {
            oneRecord = rawData.childNodes[i];
            oneObject = output[output.length] = new Object();
            for (j = 0; j < oneRecord.childNodes.length; j++)
            {
                if (oneRecord.childNodes[j].nodeType == 1)
                {
                	if ((oneRecord.childNodes[j].firstChild != null) && (oneRecord.childNodes[j].firstChild.nodeValue != null))
                	{
	                    oneObject[oneRecord.childNodes[j].tagName] =
	                        oneRecord.childNodes[j].firstChild.nodeValue;
	                }
	                else
                	{
	                    oneObject[oneRecord.childNodes[j].tagName] = "";
	                }
                }
            }
        }
    }
    return output;
}

function cloneObject(what)
{
 	var objindex = 0;
    for (objindex in what)
    {
        if (typeof what[objindex] == 'object')
        {
            this[objindex] = new cloneObject(what[objindex]);
        }
        else
        {
            this[objindex] = what[objindex];
        }
    }
}

function fnNull()
{
}

function fnAJAXCall_Post(str_loc, str_params)
{
	fnLogInfo("fnAJAXCall_Post(" + str_loc + ", "+ str_params + ");");
	// Reset our hour idle counter.  If the client is requesting data from the server, it is not idle.
	g_num_mins_since_manual_reload = 0;
	var req_index = fnIncReqArray();

	if (window.XMLHttpRequest) // Non-IE browsers or IE7+
    {
	    g_req_array[req_index] = null;
    	g_req_array[req_index] = new XMLHttpRequest();
	    g_req_array[req_index].onreadystatechange = fnNull;
	    var len=""+str_params.length;
	    fnLogInfo("str_params length="+len);
      	try
      	{
      		// The last param means async when true
       		g_req_array[req_index].open("POST", str_loc, false);
			//g_req_array[req_index].setRequestHeader("Content-Length", len);
			g_req_array[req_index].setRequestHeader("Content-Type", "text/xml");
			g_req_array[req_index].setRequestHeader("Accept-Encoding","gzip,deflate");
		}
      	catch (e)
      	{
        	alert(e);
      	}
      	g_req_array[req_index].send(str_params);
      	processStateChange();
    }
	else if (window.ActiveXObject) // Old IE
	{
		// Format the url
	  	var newurl = str_loc;

		var progIDs = ['Microsoft.XMLHttp','Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0'];
		var b_done = 0;
		var i = 0;

        for (i=0; ((i < progIDs.length) && (!b_done)); i++)
        {
 	    	try
 	       	{
				g_req_array[req_index] = new ActiveXObject(progIDs[i]);
				if (g_req_array[req_index])
					b_done = 1;
          	}
          	catch (ex)
          	{
          		fnLogError(ex);
	      	}
      	}
      	if (g_req_array[req_index] != null)
      	{      	
	        g_req_array[req_index].onreadystatechange = fnNull;
      		// The last param means async when true	        
        	g_req_array[req_index].open("POST", newurl, false);
			g_req_array[req_index].setRequestHeader("Content-Type", "text/xml");
			g_req_array[req_index].setRequestHeader("Accept-Encoding","gzip,deflate");
	        g_req_array[req_index].send(str_params);
	        processStateChange();
      	}
	}
}

function retrieveURL(url)
{
	fnLogInfo("retrieveURL(" + url + ");");
	// Reset our hour idle counter.  If the client is requesting data from the server, it is not idle.
	g_num_mins_since_manual_reload = 0;
	// append timestamp
	var url2 = url;
	var array_url = url2.split("?");
	var date1 = new Date();
	if ((array_url.length>0) && (array_url[1])&& (array_url[1]!=""))
		url2 +=	"&timestamp=" + date1.getTime();
	else
		url2 +=	"timestamp=" + date1.getTime();

	// Format the url
  	var newurl;
  	newurl = '<html:rewrite href="' + url2 + '"/>';
  	var req_index = fnIncReqArray();

	if (window.XMLHttpRequest) // Non-IE browsers or IE7+
    {
    	g_req_array[req_index] = new XMLHttpRequest();
	    g_req_array[req_index].onreadystatechange = fnNull;
      	try
      	{
      		// The last param means async when true
       		g_req_array[req_index].open("GET", url2, false);
			g_req_array[req_index].setRequestHeader("Content-Type", "text/xml");
			g_req_array[req_index].setRequestHeader("Accept-Encoding","gzip,deflate");
      	}
      	catch (e)
      	{
        	fnLogError(e);
      	}
      	g_req_array[req_index].send(null);
      	processStateChange();
    }
	else if (window.ActiveXObject) // Old IE
	{
		var progIDs = ['Microsoft.XMLHttp','Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0'];
		var b_done = 0;
		var i = 0;

        for (i=0; ((i < progIDs.length) && (!b_done)); i++)
        {
 	    	try
 	       	{
				g_req_array[req_index] = new ActiveXObject(progIDs[i]);
				if (g_req_array[req_index])
					b_done = 1;
          	}
          	catch (ex)
          	{
          		fnLogError(ex);
	      	}
      	}
      	if (g_req_array[req_index] != null)
      	{
	        g_req_array[req_index].onreadystatechange = fnNull;
      		// The last param means async when true
        	g_req_array[req_index].open("GET", newurl, false);
			g_req_array[req_index].setRequestHeader("Content-Type", "text/xml");
			g_req_array[req_index].setRequestHeader("Accept-Encoding","gzip,deflate");
	        g_req_array[req_index].send();
	        processStateChange();
      	}
	}
}

function processAJAXMsg(strIn)
{
	var	i = 0;
 	var	regEx;
 	var status_set;

	fnLogInfo("processAJAXMsg");
	fnLogInfo("strIn=" + strIn);

 	// Load the xml from the tdt_ajax message
 	fnLoadXML(strIn);

	// Status values
	regEx = new RegExp("(<status_set>)");
	if (regEx.test(strIn))
	{
  	 	// Load the status_set into the status_set array
		status_set = fnXML2JS(xdoc, "status_set");

		if (null != status_set)
		{
			for (i=0; i<status_set.length; i++)
			{
				// Run the status handler
				if ((null != status_set[i].msg_code) && ("" != status_set[i].msg_code))
				{
					fnStatusHandler(parseInt(status_set[i].msg_code, 10), status_set[i].param1);
				}
			}
		}
	}
}

function processStateChange()
{
	var i = 0;
	for (i=0; i<REQ_ARRAY_MAX; i++)
	{
		if (g_req_array[i])
		{
			if (g_req_array[i].readyState == 4) // Complete
		    {
		    	fnLogError("processStateChange: readystate=4, status="+g_req_array[i].status);
		    	if (g_req_array[i].status == 200) // OK response
		      	{
		      		fnLogError("processStateChange 200");
		      		var str_in = g_req_array[i].responseText;

				  	// validate that this is really a tdt ajax message
		      		if ((str_in == null) || (str_in == ""))
		      			return;
				  	if (('<' != str_in.charAt(0)) || ('q' != str_in.charAt(1)) || ('t' != str_in.charAt(2)) || ('>' != str_in.charAt(3)))
				  		return;
					fnLogError("processStateChange processAJAXMsg("+str_in+")");
	      			processAJAXMsg(str_in);
			    } // end of request OK
			    else if (g_req_array[i].status >= 400) // err state
			    {
				    fnLogError("processStateChange err, status =" +g_req_array[i].status);
				    //fnAJAXError(g_req_array[i].status);
			    }
			    g_req_array[i] = null;
			} // end of request Complete
		}
	}
} // end of function processStateChange

