/*
	ColdFusion AJAX Core
	
	This library is intended to be an easy to work with AJAX library for any 
	programming language. It was designed with using JavaScript as the data 
	interchance format, instead of XML. Any data interchange format should work.
	The only caveat is that most AJAX libraries provide XML parsing helpers. We
	provide none here and leave that to the client consuming the data. Which is
	why JavaScript as the data interchange format is so easyis so easy. 
	
	This software is provided under the Apache License, Version 2.0
	
	Portions of this code are from the DWR project. http://getahead.ltd.uk/dwr/
	
	Author: Jeremy Allen
*/

/**
 *
 * Main class definition
 *
 */ 
function CACore()
{	
}

// Create an associative array of batches currently being processed
CACore._batches = [];
CACore._DOMDocument = ["Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];
CACore._XMLHTTP = ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];

/**
 *
 * Method to send request to server
 *
 */ 
CACore._sendReq = function(reqData, reqURL, batchId, callbackHandler)
{
	// Create and initialize the batch
	var batch = {};	
	batch.callback = callbackHandler;
	batch.requestURL = reqURL;
	batch.key = batchId;	
	batch.map = {};
	
	// Take all of the fields from reqData and put them in the batch map	
	for(prop in reqData)
		batch.map[prop] = reqData[prop];

				
	// Create XmlHttpRequest object, IE and Mozilla cross browser.
	if (window.XMLHttpRequest) {

		
		batch.req = new XMLHttpRequest();

		// IE5 for the mac claims to support window.ActiveXObject, but throws an error when it's used		
	} else if (window.ActiveXObject && !(navigator.userAgent.indexOf('Mac') >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
	
		batch.req = this._newActiveXObject(CACore._XMLHTTP);

	}
	
	if(batch.req) {
		
		// Register a new callback handler func
		batch.req.onreadystatechange = function() { CACore._stateChange(batch); };
		
		// Always use method 2 unless you are debugging (and even then...)
		var method = 2;		
		if(method == 1) {			
			data = reqData["zipcode"];
					
			batch.req.open("GET", batch.requestURL + "?data=" + data, true);
			
			batch.req.send("");
		} else {
			// Create our HTTP query string
			query = "ajaxrequest=true&";
			
			// Count number of items in map
			maplen = 0; for(prop in batch.map) { maplen++; }
						
			// For each non function in the map encode it and add it to the query
			for (prop in batch.map)				
				if (typeof batch.map[prop] != "function")
					query += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";											
			
			// Push the batch off to the server
			batch.req.open("POST", batch.requestURL, true);			
			// This is required for CF to properly see our POST variables in the form scope.
			batch.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			batch.req.setRequestHeader('Content-Length', query.length);
			batch.req.send(query);			
			
						
		}
	}
	
	// Save the batch  (This holds all currently processing batches in memory)
	CACore._batches[batch.key] = batch;
		
	// Return the batch as the arg of this function should the caller of this
	// method wish to modify it.
	return batch;
}


/**
 *
 * Method to handle response from server
 *
 */
CACore._stateChange = function(batch)
{	

	// 4 is a magic number here that means we are ready
	if (batch.req.readyState == 4) {
		try {		
		
				// The response from the server is held in the XmlHttpRequest.responseText
				// variable. (in our case batch.req holds a ref to an XmlHttpRequest obj
				var reply = batch.req.responseText;

        if (reply != null && reply != "") {
					// If the HTTP response status is 200 (OK) then we continue
					if (batch.req.status && batch.req.status == 200) {
						// Call our callback method with our data
						batch.callback(reply);
					
						// Mark the batch as complete
            batch.completed = true;
					
						// Clean up the XML http object, this ensures we don't leak memory in IE
						delete batch.req;
					
						//alert(reply);
          } else {
						// Commented out. Not used. You may want to define CACore._stateChangeError for
						// production code
						
						//DWREngine._stateChangeError(batch, reply);
					}
       } else {				 
				 // See previous comment
				 //DWREngine._stateChangeError(batch, "No data received from server");
       }
     } catch (ex) {
		 // see previous comment
		 //DWREngine._stateChangeError(batch, ex);
   }
   //DWREngine._finalize(batch);
 }
	
	// Clear the batch out of the queue after it has been processed
	// This also prevents us from leaking memory.
	delete CACore._batches[batch.key];
	
	return reply;
	
}

/**
 * Helper to find an ActiveX object that works.
 
 * @param axarray An array of strings to attempt to create ActiveX objects from
 * @return An ActiveX object from the first string in the array not to die
 * @private
 */
CACore._newActiveXObject = function(axarray)
{
    var returnValue;    
    for (var i = 0; i < axarray.length; i++) {
        try {
            returnValue = new ActiveXObject(axarray[i]);
            break;
        }
        catch (ex) {
        }
    }

    return returnValue;
}

CACore._hexchars = "0123456789ABCDEF";
CACore._toHex = function(n)
{
		return CACore._hexchars.charAt(n >> 4) + CACore._hexchars.charAt(n & 0xF);
}

CACore._okURIchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";

function encodeURIComponent(s)
{
		var c;
		var enc = "";

		// Ensure the value we are encoding is a string (dynamic typing issue)
		s = "" + s;
		
		for (var i= 0; i<s.length; i++) {
				if (CACore._okURIchars.indexOf(s.charAt(i)) == -1) {
						enc += "%" + CACore._toHex(s.charCodeAt(i));
				}
				else {
						enc += s.charAt(i);
				}
		}

		return enc;
}
