/**
	Ajax Handler Object
	Basically a wrapper for my (and possibly your) ajax requests.
	
	@author Jacob Novero
	@version 11/27/2008
**/

	if( typeof XMLHttpRequest == "undefined" )
	  XMLHttpRequest = function() {
	    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
	    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
	    try { return new ActiveXObject("Msxml2.XMLHTTP") }     catch(e) {}
	    try { return new ActiveXObject("Microsoft.XMLHTTP") }  catch(e) {}
	    throw new Error( "This browser does not support XMLHttpRequest or XMLHTTP." )
	  };
	


	if(AJAX_PATH==undefined)
		var AJAX_PATH = "/ajax/";
	
	function AjaxRequest(url,callback,data,requestType)
	{
		if(!requestType)
			requestType="POST";
		
			
		this.terminal = false;	
		this.setURL(url);
		
		this.setCallback(callback);
		this.noExec=0;
		this.setRequestType(requestType);
		this.isJQuery=false;
		if(data)
			this.hashToRequestParams(data);
			
		this.defaultLoaderStyle = "default_loader";
		
		//objects.push(this);
		
		
		this.headers = 
		{
			"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"
	//		"Cache-Control":"max-age=360000;",
		//	"Pragma":"max-age=360000;"
		}
		
	}
	
	/**
	*
	*	displayLoader - creates a loader element for the duration of the request
	* 	@param loaderClass // css classname for the style
	*   @param loaderStyles // an associative array of run-time style attributes to fine tune the loader (index=style name; value=style value)
	*			
	**/
	AjaxRequest.prototype.setLoader = function(loaderClass,loaderStyles,parentElement)
	{
		loader = document.createElement("div");
		loader.className = (loaderClass!=undefined?loaderClass:this.defaultLoaderStyle);
		
		
		if(loaderStyles)
			for(index in loaderStyles)
				loader.style[index] = extraStyles[index];
		
		if(parentElement)	this.setLoaderParent(parentElement);	
		
		this.loader = loader;
		
		return this.loader;				
	}
	
	
	
	
	AjaxRequest.prototype.setLoaderTxt = function(string)
	{
		this.loaderText = string;
	}
	
	AjaxRequest.prototype.setLoaderIterator = function(params)
	{
		this.loaderInterval = (params.interval?params.interval:100);
		this.loaderData = params.data;
		this.loaderIterator = true;
		this.loaderTitle = params.title;
		this.loaderMethod = params.method;
		
		return this.loader;		
		
		
		this.loaderData = params.data;
	}
	
	AjaxRequest.prototype.removeLoader = function()
	{
		// make some jquery toggle, so it can still be completely independant of a 3rd party
		// same goes w/ prototype etc.
		/*
			parent.removeChild(loader.index);
		*/
		
		
		if(this.loader)	
		{
			if(this.loaderIterator)
				clearInterval(this.loadInterval);
				
			if(this.isJQuery)
				$(this.loader).remove();
			else
				this.loaderParent.removeChild(this.loader);
			
			// if jquery in use 
			//jQuery(this.loader).fadeOut(100,jQuery(this).remove());
			
		}
			
			//jQuery(this.loader).remove();
	}

	AjaxRequest.prototype.setURL = function(url)
	{
		this.url = url;
	}
	
	AjaxRequest.prototype.setCallback = function(callback)
	{
		
		if(callback.method)
		{
			this.callbackMethod = callback.method;
			this.callbackObject = callback.object;
		}
		else if(callback.match)
			this.callbackMethod = callback;
		else
			this.callbackMethod = false;
		
	}
	
	AjaxRequest.prototype.setLoaderParent = function(element)
	{
		if(element)
		{
			this.loaderParent = element;
			return this.loaderParent;
		}
		else
			this.loaderParent = document.body;
	}
	
	AjaxRequest.prototype.displayLoader = function()
	{
		if(!this.loader)
			this.loader = this.setLoader();
		
			
		if(this.loaderIterator)
		{
			var loaderTitle = document.createElement("h3");
			
			loaderTitle.innerHTML = this.loaderTitle;
			
			this.loader.appendChild(loaderTitle);
			
			var iteratorDiv = document.createElement("span");
			var iteratorIco = document.createElement("div");
			this.loader.appendChild(iteratorIco);
			this.loader.appendChild(iteratorDiv);
			
			var ajax = this;
			this.loadInterval = setInterval(
				function()
				{
					var data = ajax.loaderData.pop();
					
					if(data.status==1)
						iteratorIco.className="good";
					else
						iteratorIco.className="bad";
						
					iteratorDiv.innerHTML = data.text;
					ajax.loaderData.unshift(data);
				}
				,	
				this.loaderInterval
			);
		}	
			
		if(this.loaderText)
		{
			//this.loader.innerHTML = this.loaderText;	not sure if i should make a seperate one
//			this.loader.appendChild(document.createTextNode(this.loaderText));
			this.loader.innerHTML = this.loaderText;
		}
			
			
		if((this.isJQuery)&&(this.loaderParent))
		{
			this.loaderParent.prepend(this.loader);
		}
		else
		{
			if(!this.loaderParent)	this.loaderParent=document.body;

			this.loaderParent.insertBefore(this.loader,this.loaderParent.firstChild);
		}
		
		
	}
	
	AjaxRequest.prototype.setRequestType = function(value)
	{
		switch(value)
		{
			case "GET":
				this.requestType = "GET";
			break;
			case "POST":
			default:
				this.requestType = "POST";
		}
	}
	
	
	AjaxRequest.prototype.setAdtlParams = function(params)
	{
		if(params !== undefined)
		{
			if(params.useLoader)
			{
				if(params.isJQuery) this.isJQuery=true;
				if(params.loaderParent)	this.setLoaderParent(params.loaderParent);
				if(params.loaderClass)	this.setLoader(params.loaderClass,params.loaderStyles);
				if(params.loaderText)	this.setLoaderTxt(params.loaderText);
				if(params.loaderIterator) this.setLoaderIterator(params.loaderIterator);
				
				this.displayLoader();	
			}
			
			if(params.noExec)
				this.noExec=1;
		}
	}
	
	
	AjaxRequest.prototype.makeRequest = function(params)
	{
		if(!this.url)
			return false;
		
		// loading in last minute params before firing the request
		if(params)
			this.setAdtlParams(params);		
		
		var ajax =  new XMLHttpRequest();
		this.terminal = false;
		this.ajax = ajax;
		
		switch(this.requestType)
		{
			case "POST":
				ajax.open(this.requestType,this.url,true);
			break;
			case "GET":
			//	$("#indexBlank").text(this.url + "?" + this.params);
				ajax.open(this.requestType,this.url + "?" + this.params,true);
			break;
		}
		
		for(index in this.headers)
		{
			ajax.setRequestHeader(index,this.headers[index]);
		}
		
		
		//Pragma
	
		if(this.requestType == "POST")
			ajax.send(this.params);

		var obj = this;
			
		this.ajax = ajax;
		this.compliantRequest();
		return true;
		// if the request takes too long, then we have to kill it.
	}

	AjaxRequest.prototype.hashToRequestParams = function(data)
	{
		var params = "";
		
		for(key in data)
			params += key + "=" + data[key] + "&";
				
		this.params = params;	
			
		return params;
	}
	
	AjaxRequest.prototype.addHeader = function(header,content)
	{
		this.headers[header] = content;
	}
	
	
	AjaxRequest.prototype.logout =function()
	{
		// this is intended to be abstracted; basically if a session expires with the logout flag, this
		// will get called and save the user from unsynced requests
		window.open(BASE_PATH + "/logout/","_self");
	}
	
	AjaxRequest.prototype.terminateRequest = function(callback)
	{
		if(callback)
		{
			if(this.callbackMethod)
			{
				var data = {
					error:
					{
						message:"We were unable to process your request",
						hint:"sorry :(",
						type:"MAX_EXECUTION"
					}
				};
				
				if(this.callbackObject)
					this.callbackObject[this.callbackMethod](data);
				else
					eval(this.callbackMethod + "(data)" + ";");
			}
		}
		
		this.ajax.abort();
		this.terminal = true;
	}

	AjaxRequest.prototype.showTimer = function(time)
	{
		if(document.getElementById("timer") == null)
		{
			var timerArea = document.createElement("div");	
			timerArea.id="timer";
			
			timerArea.onclick = function()
			{
				$(this).remove();
			}
			
		}
		else
		{
			var timerArea = document.getElementById("timer");
		}
		
		timerArea.innerHTML = time;		
		$("body").prepend(timerArea);
	}
	
		
	AjaxRequest.prototype._destruct = function()
	{
		for(var i in this)
			this[i] = null;
		
		killself(this);
	}
	
	AjaxRequest.prototype.compliantRequest = function()
	{
		this.resultbuffer = "";
		var ajax = this.ajax;
		var object = this;
		var stream = false;
		this.ajaxInterval = setInterval(
			function()
			{
				if(object.terminal)
				{
					object.removeLoader();
					clearInterval(object.ajaxInterval);
				}	
				
				try
				{
					if((typeof object.ajax.status=="undefined")||(object.ajax.status != 200))
					{
						return false;
					}
				}
				catch(e)
				{
					return false;
				}
				
				
					
				
				
				if((object.ajax!=null)&&(object.ajax.status!=null))
				{
					if((object.ajax.readyState != 4 && object.ajax.status==200)&&(stream))
					{
						if(object.ajax.responseText != object.resultbuffer)
						{
							var json = object.ajax.responseText.replace(object.resultbuffer,"");
							
//							data = json;
							
							object.resultbuffer = object.ajax.responseText; // now take full set and make it resultBuffer
	
							eval(object.callbackMethod + "(data)" + ";");
						}
					}
				}
				
				
				if(object.ajax.readyState == 4 && object.ajax.status==200)
				{
					if(object!=null)
						object.removeLoader();
						
//					clearTimeout(object.terminator);
					clearInterval(object.ajaxInterval);

					var json = object.ajax.responseText.toString().replace(object.resultbuffer,"");
					
					
					if(!object.noExec)
						eval("var data = " + json + ";");
					else
						data = json;
					
					
					// handle session deaths in this object itself
					if(data == "logout")
						object.logout();
					
					
					if(object.callbackMethod)
					{
						if(object.callbackObject)
							object.callbackObject[object.callbackMethod](data);
						else
							eval(object.callbackMethod + "(data)" + ";");
					}
				}
				
		    	if(object.terminal)
		    		object.ajax.abort();
		    		
			}
		,50);

		if(this.requestType == "GET")
			ajax.send(null);

	}
	
	
	/*
	    ajax.onreadystatechange = function()
	    {
	    	if(this.object.terminal)
	    		ajax.abort();
	    		
	    		
			if (ajax.readyState == 4 && ajax.status == 200)
			{
				if(
					(navigator.getBrowserCode() == browser.IE)&&
					(DEBUG_MODE)
				)
				{
					var area = document.createElement("p");
					var area2 = document.createElement("p");
					$(area).text(ajax.responseText);
					$(area2).text(this.object.url + "?" + this.object.params);
					$("body").append(area);
					$("body").append(area2);
				}
					
				if(this.object!=null)
					this.object.removeLoader();
				
				
				clearTimeout(this.object.terminator);
				
				if(!this.object.noExec)
					eval("var data = " + ajax.responseText + ";");
				else
					data = ajax.responseText;
				
				// handle session deaths in this object itself
				if(data == "logout")
					this.object.logout();
				
				if((DEBUG_MODE)&&(data.timer!=undefined))	
				{
					this.object.showTimer(data.timer);
				}
					
				
				if(this.object.callbackMethod)
				{
					if(this.object.callbackObject)
						this.object.callbackObject[this.object.callbackMethod](data);
					else
						eval(this.object.callbackMethod + "(data)" + ";");
				}
				
			}
			else if(ajax.readyState == 4 )
			{
				this.object.removeLoader();
			}
	
	    }
	    
	    
		if(this.requestType == "GET")
			ajax.send(null);
	*/