/**
* JavaScript AJAX ToolKit
*
* Developed primarily for implementing AJAX Framework
* This class can be customized to suit the needs. One can use the accessor
* methods to initialize the object and also add accessor methods to implement
* the class methods externally by using Object Inheritance.
* 
* This class requires some parameters to initialize it has one 
* function called init() which initializes this object by the parameters
* passed.
*
* @async		boolean		true|false		determines asynchronous/synchronous calls to be made to server
* @req_mode		string		GET|POST		type of request can be either GET|POST
* @resp_type	string		XML|TEXT		type of response be returned from server
* @url			string		URL				url of the server side file to which calls to be made
* @params		string		parameters		querystring params @req_type, can be blank
* @callback_func string		callback()		call back function name after processing this func() will be called
*											for further processing of the response to clientside. 
*											WILL GENERATE ERROR IF callback_func() OMITTED DURING init()
*
* Usage:
*		Just call the object from client side like the following:
*		var x = new AJAX();
*		and then call the init() method with params to initialize the object state
*		x.init('true', 'GET', 'XML','somefile.jsp','name=Arnab&desig=Ajax+Programmer',sampleXMLParser);
*		
*		Public Functions :
*		x.getConfigDetails(); // Displays object config detail, must be called after init()
*		x.call_ajax(); // Does the actual connecting, and retrieving function must be called after init()
*		
* version:	1.0
*/
function AJAX() {

	/**
	* configuration options for this class
	* Local variables local to class
	*/

	/** asynchronous or synchronous transfer mode flag */
	var async = true;	

	/* GET/POST request mothods */
	var request_mode = 'GET';
	

	/* TEXT/XML response type */
	var response_type = 'XML';

	/* remote url */
	var url = '';

	/*	querystring parameters  */
	var params = '';

	/* use persistent connection  */
	var persist_conn = false;

	/* determines the object is fully initialized */
	var isInitialized = false;		
	
	/**
	* client callback function to
	*/
	var client_callback = null;

	/**
	* switches the debugging to on/off
	* 0 = off, 1 = on
	*/
	var debugging = 0;
	
	/**
	* XMLHttpRequest object used in this request
	* @var		object		xmlHttp
	*/
	var xmlHttp = false;	
	
	/**
	* This function sets whether to use asynchronous calls or not
	*
	* @access	public
	* @param	async	synchronization flag
	* @return void
	*/
	var set_async = function () {		
		if (typeof arguments[0] == 'boolean') {
		    async = arguments[0];
		}
	}	
	
	/**
	* Sets the response type
	*	Allowed Values:
	*	TEXT	= Raw text response from XMLHttpObject
	*	XML		= Raw XML response from XMLHttpObject
	*	
	* Default response type is XML
	* @param	string		response_type	response_type
	* @return	void
	*/
	var set_response_type = function () {		
		if (arguments[0].toUpperCase() == 'TEXT' || arguments[0].toUpperCase() == 'XML') {
		    response_type = arguments[0].toUpperCase();
		}
	}

	/**
	* sets the transfer_mode (GET|POST).
	*	
	* @param    string    transfer_mode    transfer_mode
	* @return   void
	*/
	var set_request_mode = function() {		
		if (arguments[0].toUpperCase() == 'GET' || arguments[0].toUpperCase() == 'POST') {
			request_mode = arguments[0].toUpperCase();
		}
	}

	/**
	* sets the URL to connect
	*
	* @param	string		url		url to connect
	* @return	void
	*/
	var set_url = function () {
		if (typeof arguments[0] == 'string') {			
		    url = arguments[0];			
		}
	}

	/**
	* sets flag whether to use persistent connections or not
	*
	* @param	boolean		persist_connect		persistent connection flag
	* @return void
	*/
	var set_persist_con = function () {
		if (typeof arguments[0] == 'boolean') {
		    persist_conn = arguments[0];
		}
	}

	/**
	* sets the parameters for the remote url
	*
	* @param	string		params		remote parameters
	* @return void
	*/
	var set_params = function () {
		if (typeof arguments[0] == 'string') {
		    params = arguments[0];
		}
	}
	

	var set_client_callback = function () {
		if (typeof arguments[0] == 'function') {
		    client_callback = arguments[0];
		}
	}

	/**
	* debugging function checks the debugging mode and alerts error
	*
	* @param	string,int		msg,debug_lvl shows according to debugging level
	* @return	void
	*/
	var debug = function (msg, debug_lvl) {		
		if (debugging > debug_lvl) {			
		    alert(msg);
		}
	}


	/**
	* creates the XMLHttpRequest object
	* @return	boolean	
	*/
	var getXHRObject = function () {
		var ret_val = false;
		var new_con = false;

		//check for persistent connection
		if (persist_conn == false) {
		    // no persistence create a new obj each time
			debug('Using new XmlHttp object', 0);
			new_con = true;
		}else {
		     //using persistence connection
			 debug('Using shared object', 0);
			 new_con = true;
		}

		if (new_con) {
		    try {
				// use latest XMLHttp object from MSIE
		        xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
		    }
		    catch (e){
		        try {
					// use this if the above one is not available
		            xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
		        }
		        catch (ex){
		            xmlHttp = null;
		        }
		    }
			// create object for Mozilla, Netscape and others
			if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
			    xmlHttp = new XMLHttpRequest();
			}

			if (xmlHttp == null || typeof xmlHttp == 'undefined') {
			    debug("[AJAX Error]\nCouldn't create XMLHttp object", 1);
			}else {				
			    ret_val = true;
			}
			return ret_val;
		}		
	}


	/**
	* this function handles xmlHttp request/response, 
	* performs any call_back operation
	*/
	this.call_ajax = function () {		
		var remote_url = '';
		//create XmlHttp connection object
		var isCreated = getXHRObject();		
		
		if (isCreated) {		
			
			if (params != '' && request_mode == 'GET') {
				remote_url = url + '?' + params;
			}else {
				remote_url = url;
			}

			// open http object for transaction
			//alert(request_mode+ "---"+remote_url+ "---" +async);
			xmlHttp.open(request_mode, remote_url, async);

			//send urlencoded header if 'request_mode' is POST
			if (request_mode == 'POST') {
				try {
					xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					xmlHttp.setRequestHeader("Content-length",params.length);
					xmlHttp.setRequestHeader("Connection","close");
				} catch (e) {
					debug('[AJAX Error]\n POST failed due to incompatible browser. Use GET instead.', 1);
				}
			}

			// callback handling for asynchronous calls
			xmlHttp.onreadystatechange = internal_callback;

			// send content
			if (request_mode == 'GET') {
				xmlHttp.send(null);    
			}else {
				xmlHttp.send(params);
			}				

			if (async == false) {
			  // manual callback handling for synchronized calls
			  internal_callback();
			}
		}else {
		     client_callback(null);
		}
	}

	/**
	* checks the request state and then performs the response fetching operation
	*
	* @return	string		response
	*/
	var internal_callback = function () {		
		var response = null;				
		if (xmlHttp.readyState == 4) {
		    if (xmlHttp.status == 200) {
		        //determine the response type				
				switch (response_type.toUpperCase()) {
					case 'TEXT':
						response = xmlHttp.responseText;
						break;
					case 'XML':						
						response = xmlHttp.responseXML;
						break;
					case 'OBJECT':
						response = xmlHttp.responseXML;
						response = convertJSONObject(response);
						break;
					default:
						debug("[AJAX ERROR]\n Invalid Response Type '" + response_type + "'", 1);
				}
		    }
		}

		// call client side call back function here
		if (response != null && typeof client_callback == 'function') {
		    client_callback(response);
		}
	}

	/**
	* The following function takes the XML output as parameter
	* and then converts the xml into JSON Array object.
	* The JSON array can then be accessed like below
	* JSONArray[0].key (will return XML tag Name)
	* JSONArray[0].value ( will return XML tag value )
	* IT WON'T CONVERT PROPERLY ANY XML TAG WHICH CONTAINS ATTRIBUTES
	* ***NOT***    <tag name="name1" type="ctype"> 
	*/
	function convertJSONObject() {
		var xmlElemArr = arguments[0];
	}


	/**
	* Initialiazes the object with the parameters
	*
	* @param	boolean		async			whether to use asynchoronous calls
	* @param	string		req_mode		request/transfer mode (GET | POST)
	* @param	string		resp_type		response type (TEXT | XML) default is XML
	* @param	string		url				remote URL to call
	* @param	string		params			parameters to send with the request
	* @param	function	callback_func	performs post-processing operations
	* @return void
	*/	
	this.init = function (async, req_mode, resp_type, path, param, callback) {	
		//call the functions to initialize object properties
		
		// initialize async value
		set_async(async);	
		
		// initialize request type
		set_request_mode(req_mode);		

		// initialize reponse type
		set_response_type(resp_type);		

		// initialize url
		set_url(path);		

		// initialize parameters
		set_params(param);
		
		// initialize persistent connection
		//this.set_persist_con(false);

		// initialize client callback function
		set_client_callback(callback);		
		
		// initialization complete
		isInitialized = true;		
		
		/**
		* call call_ajax method to handle xmlhttp request
		*/
		this.call_ajax();
		}

		this.getConfigDetail = function () {		
			alert("Configuration Details:\n-----------------------------------------\n\nAsynchronous:\t\t"+async+"\nRequest Mode:\t\t"+request_mode+"\nResponse Type:\t\t"+response_type+"\nURL:\t\t\t"+url+"\nParameters:\t\t"+params+"\nCallback Func:\t\t"+client_callback);
		}
}