/*

Written by Ali Çevik for Bilkent University	Online Courses (MOODLE)

a_cevik@ug.bilkent.edu.tr

07.02.08

http://www.alicevik.net

http://www.bilkent.edu.tr

*/

// AsyncRequest class for AJAX

function AsyncRequest()
{

	// property fields

	// xmlhttp request obj
	this.requestObj =  null;
	
	// variables to pass
	this.variables = '';

	// request url
	this.url = '';

	// success case handler
	this.successCallback = '';

	// failure case handler
	this.failureCallback = '';

	// loading case handler
	this.loadingCallback = '';

	// form method. (POST or GET)
	this.method = '';
	
	this.cachingMechanism = null;
	
	// accessor and mutator methods
	this.setRequestObj = function(_requestObj)
	{
		this.requestObj = _requestObj;
	}
	
	this.getRequestObj = function()
	{
		return this.requestObj;
	}
	
	this.setVariables = function(_variables)
	{
		this.variables = _variables;
	}
	
	this.setCachingMechanism = function(cm)
	{
		this.cachingMechanism = cm;
	}
	
	this.getVariables = function()
	{
		return this.variables;	
	}

	this.setUrl = function(_url)
	{
		this.url = _url;
	}

	this.getUrl = function()
	{
		return this.url;
	}
	
	this.setMethod = function(_method)
	{
		this.method = _method;
	}

	this.getMethod = function()
	{
		return this.method;
	}

	this.setSuccessCallback = function(_successCallback)
	{
		this.successCallback = _successCallback;
	}
	
	this.getSuccessCallback = function()
	{
		return this.successCallback;
	}

	this.setFailureCallback = function(_failureCallback)
	{
		this.failureCallback = _failureCallback;
	}
	
	this.getFailureCallback = function()
	{
		return this.failureCallback;
	}

	this.setLoadingCallback = function(_loadingCallback)
	{
		this.loadingCallback = _loadingCallback;
	}

	this.getLoadingCallback = function()
	{
		return this.loadingCallback;
	}


	this.createRequestObj = function()
	{
		var _requestObj = null;
		
		if (window.ActiveXObject)
		{
			_requestObj = new ActiveXObject("Microsoft.XMLHTTP");
		}	
		else if (window.XMLHttpRequest)
		{
			_requestObj = new XMLHttpRequest();
		}

		this.setRequestObj(_requestObj);
	}

	this.setHeaders = function()
	{
		var _requestObj = this.getRequestObj();

		_requestObj.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
		_requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=iso-8859-9");

		this.setRequestObj(_requestObj);
	}
	
	this.setCallbacks = function()
	{
		var _requestObj = this.getRequestObj();
		var _successCallback = this.getSuccessCallback();
		var _failureCallback = this.getFailureCallback();
		var _loadingCallback = this.getLoadingCallback();
	
		if (_requestObj == null)
			return;
		var instance = this;
		_requestObj.onreadystatechange = function(url)
		{
			// if ready
			if (_requestObj.readyState == 4)
			{
				// if success
				
					if (_requestObj.status == 200 || _requestObj.status == 304)
					{
						_successCallback(_requestObj);
					
						if (instance.cachingMechanism != null)
						{
							var obj = null;
							try
							{
								obj = JSON.parse(_requestObj.responseText);
							}
							catch (e)
							{
								obj = _requestObj.responseText;	
							}
						
							instance.cachingMechanism.createCache(instance.getCacheKey(), obj );
						}

					}
					// other than "communication failure" in firefox
					else if (_requestObj.status != 0 )
					{
						_failureCallback(_requestObj);
					}
					  
					
			}	
			// not ready yet, call loading callback
			else
			{
				_loadingCallback();
			}
		
		}
		
		this.setRequestObj(_requestObj);
	
	}
	
	// instantiate xmlhttprequest obj
	this.openAsyncRequest = function()
	{
		var _requestObj = this.getRequestObj();

		_requestObj.open(this.getMethod(), this.getUrl(), true);

		this.setRequestObj(_requestObj);

	}
	
	// send the variables to request obj
	this.sendVariables = function()
	{
		var _requestObj = this.getRequestObj();

		_requestObj.send(this.getVariables());

		this.setRequestObj(_requestObj);
	}

	this.getCacheKey = function()
	{
		return hex_md5(this.getUrl() + this.getVariables() + this.getMethod()) ;
	}

	this.checkCache = function()
	{
		var cacheMode = false;
	
		if (this.cachingMechanism != null)
		{
			
			var cacheObj = this.cachingMechanism.retrieve( this.getCacheKey() );
				
			if (cacheObj != null)
			{
				cacheMode = true;
				var o = new Object;
				if (typeof(cacheObj) == "object")
				{
					o.responseText = JSON.stringify(cacheObj);
				}
				else
				{
					o.responseText = cacheObj;
				}
			
				var successCallback = this.getSuccessCallback();		
				successCallback(o);
			}
		}
		
		return cacheMode;
	}
	// call this from outside to start the process
	this.makeRequest = function()
	{
		
		if (!this.checkCache())
		{
			this.createRequestObj();
	
			this.openAsyncRequest();
	
			this.setHeaders();
			
			this.setCallbacks();
			
			this.sendVariables();
		}
	}

	this.defaultSuccessCallback = function(o)
	{
		alert(o.responseText);
	}

	this.defaultFailureCallback = function(o)
	{
		alert(o.statusText);
	}

	this.defaultLoadingCallback = function(o)
	{
		// do nothing!
	}

	// set default callbacks
	this.setSuccessCallback(this.defaultSuccessCallback);
	this.setFailureCallback(this.defaultFailureCallback);
	this.setLoadingCallback(this.defaultLoadingCallback);

}

