//The allofe AJAX class.
//If there are changes, be SURE you know what it's affecting
//Preferable changes = changes to internal working not the syntax!

function aoeAJAX(requestFile) {
	this.failed = null;
	this.xmlhttp = null;
	this.sendData = null;
	this.callbackFunctionName = null;
	this.callbackJSObjectName = null;
	this.callbackJSObjectFunction = null;
	this.response = null;
	this.URLString = "";
	this.requestFile = requestFile;
	this.method = "post";
	
	this.onLoading = function() { };
	this.onLoaded = function() { };
	this.onInteractive = function() { };
	this.onCompletion = function() { };
	
	this.createAJAX = function() {
		try {
			this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (oc) {
				this.xmlhttp = null;
			}
		}
		if(!this.xmlhttp && typeof XMLHttpRequest != "undefined")
			this.xmlhttp = new XMLHttpRequest();
		if (!this.xmlhttp){
			// no XMLHttpRequest support, so no AJAX.
			this.failed = true; 
		}
	}
	
	this.setMethod = function(method) {
		this.method = method;
	}
	
	this.getMethod = function(method) {
		return this.method;
	}
	
	this.setSendData = function(data) {
		this.sendData = data;
	}
	
	this.setResponseCallback = function(callbackFunctionName) {
		this.callbackFunctionName = callbackFunctionName;
	}

	this.getURLString = function(){
		var newSendData = new Array();
		for(var key in this.sendData) {
			if (typeof(this.sendData[key])!="function") {
				if (this.encodeURIString) {
					if (key.indexOf('amp;') != -1){
						key = key.substring(4);
					}
					newSendData[newSendData.length] = encodeURIComponent(key)+"="+encodeURIComponent(this.sendData[key]);
				}
				else {
					theData = ""+this.sendData[key];
					if ((theData.indexOf('&') != -1) || (theData.indexOf('+') != -1)) { this.sendData[key] = encodeURIComponent(this.sendData[key]); }
					newSendData[newSendData.length] = key+"="+this.sendData[key];
				}
			}
		}
		return newSendData.join('&');
	}
	
	this.send = function() {
		if (this.xmlhttp) {
			var self = this; // wierd fix for odd behavior where "this" wouldn't work in the readystate function.
			this.xmlhttp.open(this.method, this.requestFile, true);
			if (this.method == "post") { this.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') }
//			if (this.method == "post") { this.xmlhttp.setRequestHeader('Content-Type', 'application/multipart-form-data') }
//alert(this.getURLString());
			this.xmlhttp.send(this.getURLString());
			this.xmlhttp.onreadystatechange = function() {
				switch (self.xmlhttp.readyState){
					case 1: // Loading.
						self.onLoading();
					break;
					case 2: // Loaded.
						self.onLoaded();
					break;
					case 3: // Interactive - is called every 4096 bytes.. pretty much just tells you it's downloading data.
						self.onInteractive();
					break;
					case 4: // Completed.
						self.response = self.xmlhttp.responseText
						self.onCompletion();
						if(self.callbackFunctionName){ self.runCallback(); }
					break;
				}
			};
		}
	}

	// Initialize the xmlhttp object
	this.createAJAX();
}

aoeAJAX.prototype.runCallback = function() {
		if (typeof(this.callbackFunctionName) == "object")
		{
			this.callbackFunctionName[0][this.callbackFunctionName[1]](this.response);
		}
		else
		{
			var callback = eval(this.callbackFunctionName);
			callback(this.response);
		}
	};

function exec_ajax(the_data, callback, the_url) {
	var exec_ajax_obj = new aoeAJAX(the_url);
	exec_ajax_obj.setResponseCallback(callback);
	exec_ajax_obj.setMethod("post");
	exec_ajax_obj.setSendData(the_data);
	exec_ajax_obj.send();
}

function exec_ajax_js_function(the_data, callback_js_obj, callback_js_fn, the_url){
	var exec_ajax_obj = new aoeAJAX(the_url);
	exec_ajax_obj.setResponseCallback({0:callback_js_obj,1:callback_js_fn});
	exec_ajax_obj.setMethod("post");
	exec_ajax_obj.setSendData(the_data);
	exec_ajax_obj.send();
}

function exec_ajax_php(the_data, callback, ajax_php_id) {
	the_data["ajax_php_id"] = ajax_php_id;
	exec_ajax(the_data, callback, "../../common/includes/ajax_exec.ahtml");
}

//quickly exec js also it makes sure that external js files are loaded before non-external js
//regexp will be faster than string searches on large html files
//this function does create two global vars window.scriptsLoading  and window.loadScript for keeping track
//of the number of scripts still loading  and storing the non-external js until it's ready to be ran
//- leaving comments in until this is tested more
// NOTE:  if a script file with a src fails to load because it is a 404 then the onload and readyState never happens.
//		  This means that the script block w/o a src will never load.
function exec_javascript(response) {
	//process external js
	var regexp = /<script[^>]*src\s?=\s?['"]([^'">]*)['"][^>]*>/gi;
	window.scriptsLoading = 0;
	while ((src = regexp.exec(response))) {
		window.scriptsLoading++;
		var scriptTag = document.createElement("script");
		scriptTag.onload = function() {window.scriptsLoading--;}
		//remember how I hate IE?
		//IE does not fire an onload event so we use onreadystatechange
		//though there is some question about if readyState will pass through both
		//"loaded" and "complete" or if it will only do one or the other
		//seems to only do one but if we get issues with external js loading after
		//non-external js this is a good place to start looking
		scriptTag.onreadystatechange= function () {
      		//console.log('ready state change for script '+this.src+': '+this.readyState);
      		if (this.readyState == 'complete' || this.readyState == 'loaded') {window.scriptsLoading--;}
   		}
		scriptTag.language = 'javascript';
		scriptTag.type = 'text/javascript';
		scriptTag.src = src[1];
		document.body.appendChild(scriptTag);
	}
	//process non-external js
	var script,scripts =[],regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
	while ((script = regexp.exec(response))) scripts.push(script[1]);
	scripts = scripts.join('\n');
	
	var script = document.createElement("script");
	script.setAttribute('language', 'javascript');
	script.setAttribute('type', 'text/javascript');
	script.text = scripts;

	// NOTE:  This code is not robust enough.
	// 		  It does not take into account where more than one ajax call is made at the same time
		
	//if we have includes be sure they run before the non-external-js
	if (window.scriptsLoading == 0) {
		document.body.appendChild(script);
	}
	else {
		// we can't load the scripts right now, so lets check again in 100ms
		window.loadScript = script;
		window.scriptInterval = window.setInterval(
			function() {
				//console.log('Scripts still loading: '+window.scriptsLoading);
				if (window.scriptsLoading==0) {
					if (window.loadScript!=null) {
						document.body.appendChild(window.loadScript);
						window.loadScript = null;
					}
					clearInterval(window.scriptInterval)
				}
			},100);
	}
}

/*if (typeof console == 'undefined') {
	console = {
		log : function(message) {
			var div = document.createElement('div');
			div.innerHTML = 'Console.log - '+message;
			document.body.appendChild(div);
		}
	}
}*/

