/*
Written by Jonathan Gros-Dubois (Modset) http://www.modset.net/.
Distributed under GNU General Public License v3.
*/

var JumboAPI = new (function() {
	var self = this;
	var JQUERY_REQUIRED_ERROR = "Error - This function needs JQuery to run.";
	var IE = self.IE = /*@cc_on!@*/false;
	
	var getCurrentPageName = self.getCurrentPageName = function() {
		var regex = new RegExp("[^/.]+(?=[.][^./]+$)");
		var res = location.href.match(regex);
		var curPage = "";
		if(res) {
			curPage = res[0];
		}
		return curPage;
	};
	
	// this function must be called from within an app iframe - It needs JQuery to run
	// returns the app's current frame width - This can be used to resize the content of the app
	var getAppFrameWidth = self.getAppFrameWidth = function() {
		if(typeof jQuery == 'undefined') {
			throw JQUERY_REQUIRED_ERROR;
		} else {
			var iframeBody = $(document.body);
			
			var iframes = $(parent.document.body).find("iframe");
			var tempContent = null;
			var width = null;
			
			iframes.each(function(index, element) {
				tempContent = $(element).contents();
				if(tempContent) {
					if(tempContent[0] == document) {						
						width = $(element).width();
						return false;
					}
				}
			});
			return width;
		}
	};
	
	// this function must be called from within an app iframe - It needs JQuery to run
	// resizes app frame to fit its content
	var autoFitAppFrame = self.autoFitAppFrame = function() {
		if(typeof jQuery == 'undefined') {
			throw JQUERY_REQUIRED_ERROR;
		} else {
			var refit = function() {
				var iframeBody = $(document.body);
				
				var iframes = $(parent.document.body).find("iframe");
				var iframesContent = iframes.contents();
				var tempContent = null;
				
				iframesContent.each(function(index, element) {
					tempContent = $(element);
					if(tempContent) {
						if(tempContent[0] == document) {
							var width = $(element).width();				
							var height = $(element).height();
							iframes.eq(index).css({'width': width + 'px', 'height': height + 'px'});
							return false;
						}
					}
				});	
			}
			
			$(window).load(refit);
			var interval = setInterval(refit, 50);
		}
	};
	
	// this function must be called from within an app iframe - It needs JQuery to run
	// returns the app's current frame height - This can be used to resize the content of the app
	var getAppFrameHeight = self.getAppFrameHeight = function() {
		if(typeof jQuery == 'undefined') {
			throw JQUERY_REQUIRED_ERROR;
		} else {
			var iframeBody = $(document.body);
			
			var iframes = $(parent.document.body).find("iframe");
			var tempContent = null;
			var height = null;
			
			iframes.each(function(index, element) {
				tempContent = $(element).contents();
				if(tempContent) {
					if(tempContent[0] == document) {						
						height = $(element).height();
						return false;
					}
				}
			});
			return height;
		}
	};
	
	var getPageSize = self.getPageSize = function() {
		var xScroll, yScroll;
		
		if(window.innerHeight && window.scrollMaxY) {	
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if(document.body.scrollHeight > document.body.offsetHeight) {
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight
		} else {
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
			
			if(IE) {
				yScroll += 20;
			}
		}
		
		var windowWidth, windowHeight;
		
		if(self.innerHeight) {
			if(document.documentElement.clientWidth) {
				windowWidth = document.documentElement.clientWidth; 
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if(document.documentElement && document.documentElement.clientHeight) {
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if(document.body) {
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	
		
		if(yScroll < windowHeight) {
			pageHeight = windowHeight;
		} else { 
			pageHeight = yScroll;
		}
		
		if(xScroll < windowWidth) {	
			pageWidth = xScroll;		
		} else {
			pageWidth = windowWidth;
		}
		
		return [pageWidth, pageHeight];
	}
	
	var findParentNode = self.findParentNode = function(element, type, maxTraceNum) {
		if(!maxTraceNum) {
			maxTraceNum = 10;
		}
		type = type.toUpperCase();
		
		if(element.nodeName.toUpperCase() == type) {
			return element;
		}
		var curElement = element.parentNode
		var count = 0;
		while(curElement && count < maxTraceNum) {
			if(curElement.nodeName.toUpperCase() == type) {
				return curElement;
			}
			curElement = curElement.parentNode;
			count++;
		}
		return null;
	}
	
	var findParentNodeByClass = self.findParentNodeByClass = function(element, className, maxTraceNum) {
		if(!maxTraceNum) {
			maxTraceNum = 10;
		}
		
		if(element.className && element.className.match(new RegExp(className))) {
			return element;
		}
		var curElement = element.parentNode
		var count = 0;
		while(curElement && count < maxTraceNum) {
			if(curElement.className && curElement.className.match(new RegExp(className))) {
				return curElement;
			}
			curElement = curElement.parentNode;
			count++;
		}
		return null;
	}
	
	var findChildNodeByClass = self.findChildNodeByClass = function(element, className, maxTraceNum) {
		if(!maxTraceNum) {
			maxTraceNum = 10;
		}
		
		var fringe = new Array();
		fringe.push(element);
		
		var children;
		var len;
		var curClass;
		var count = 0;
		var curEl;
		
		while(fringe.length > 0 && count < maxTraceNum) {
			curEl = fringe.shift();
			
			curClass = curEl.className;
			
			if(curClass && curClass.match(new RegExp(className))) {
				return curEl;
			}
			
			children = curEl.childNodes;
			if(!children) {
				return null;
			}
			
			len = children.length;
			
			for(var j=0; j<len; j++) {
				fringe.push(children[j]);
			}
			count++;
		}
		return null;
	}
	
	var findRelatedNodeByClass = self.findRelatedNodeByClass = function(element, className, maxTraceNum) {
		var node = findParentNodeByClass(element, className, maxTraceNum);
		if(!node) {
			return findChildNodeByClass(element, className, maxTraceNum);
		}
		return node;
	}
	
	/*
		Developed by Robert Nyman, http://www.robertnyman.com
		Code/licensing: http://code.google.com/p/getelementsbyclassname/
	*/
	var getElementsByClassName = self.getElementsByClassName = function (className, tag, elm) {
		if (document.getElementsByClassName) {
			getElementsByClassName = function (className, tag, elm) {
				elm = elm || document;
				var elements = elm.getElementsByClassName(className),
					nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
					returnElements = [],
					current;
				for(var i=0, il=elements.length; i<il; i+=1){
					current = elements[i];
					if(!nodeName || nodeName.test(current.nodeName)) {
						returnElements.push(current);
					}
				}
				return returnElements;
			};
		}
		else if (document.evaluate) {
			getElementsByClassName = function (className, tag, elm) {
				tag = tag || "*";
				elm = elm || document;
				var classes = className.split(" "),
					classesToCheck = "",
					xhtmlNamespace = "http://www.w3.org/1999/xhtml",
					namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
					returnElements = [],
					elements,
					node;
				for(var j=0, jl=classes.length; j<jl; j+=1){
					classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
				}
				try	{
					elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
				}
				catch (e) {
					elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
				}
				while ((node = elements.iterateNext())) {
					returnElements.push(node);
				}
				return returnElements;
			};
		}
		else {
			getElementsByClassName = function (className, tag, elm) {
				tag = tag || "*";
				elm = elm || document;
				var classes = className.split(" "),
					classesToCheck = [],
					elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
					current,
					returnElements = [],
					match;
				for(var k=0, kl=classes.length; k<kl; k+=1){
					classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
				}
				for(var l=0, ll=elements.length; l<ll; l+=1){
					current = elements[l];
					match = false;
					for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
						match = classesToCheck[m].test(current.className);
						if (!match) {
							break;
						}
					}
					if (match) {
						returnElements.push(current);
					}
				}
				return returnElements;
			};
		}
		return getElementsByClassName(className, tag, elm);
	};
	
	var AjaxEngine = self.AjaxEngine = {
		httpReq: new XMLHttpRequest(),
		busy: false,
		processQueue: new Array(),
		callback: null,
		cancelling: false,
		appendCacheKillerToURL: function(url) {
			var mck = /(\?|&)mck=/;
			if(!mck.test(url)) {
				var qreg = /\?/;
				if(qreg.test(url)) {
					url += "&mck=" + new Date().getTime();
				} else {
					url += "?mck=" + new Date().getTime();
				}
			}
			return url;
		},
		post: function(url, callback, tupleList) {
			AjaxEngine.cancelling = false;
			
			if(AjaxEngine.busy) {
				AjaxEngine.processQueue.push({method:"post", url:url, callback:callback, tupleList:tupleList});	
			} else {
				AjaxEngine.busy = true;
				AjaxEngine.callback = callback;
				var varslen = (tupleList ? tupleList.length : 0);
				var sendVars = "";
				var isArray = false;
				if(varslen > 0) {
					if(checkIsArray(tupleList[0])) {
						sendVars = encodeURIComponent(tupleList[0][0]) + "=" + encodeURIComponent(tupleList[0][1]);
						isArray = true;
					} else {
						sendVars = encodeURIComponent(tupleList[0].name) + "=" + encodeURIComponent(tupleList[0].value);
					}
				}
				if(isArray) {
					for(var i=1; i<varslen; i++) {
						sendVars = sendVars + "&" + encodeURIComponent(tupleList[i][0]) + "=" + encodeURIComponent(tupleList[i][1]);
					}
				} else {
					for(var i=1; i<varslen; i++) {
						sendVars = sendVars + "&" + encodeURIComponent(tupleList[i].name) + "=" + encodeURIComponent(tupleList[i].value);
					}
				}
				
				url = AjaxEngine.appendCacheKillerToURL(url);
				
				AjaxEngine.httpReq.open("POST", url, true);
				
				AjaxEngine.httpReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				
				AjaxEngine.httpReq.send(sendVars);	
				AjaxEngine.httpReq.onreadystatechange = AjaxEngine.readyStateChange;
			}
		},
		get: function(url, callback, tupleList) {
			AjaxEngine.cancelling = false;
			
			if(AjaxEngine.busy) {
				AjaxEngine.processQueue.push({method:"get", url:url, callback:callback, tupleList:tupleList});	
			} else {
				AjaxEngine.busy = true;
				AjaxEngine.callback = callback;
				var varslen = (tupleList ? tupleList.length : 0);
				var sendVars = "";
				var isArray = false;
				if(varslen > 0) {
					if(checkIsArray(tupleList[0])) {
						sendVars = "?" + encodeURIComponent(tupleList[0][0]) + "=" + encodeURIComponent(tupleList[0][1]);
						isArray = true;
					} else {
						sendVars = "?" + encodeURIComponent(tupleList[0].name) + "=" + encodeURIComponent(tupleList[0].value);
					}
				}
				if(isArray) {
					for(var i=1; i<varslen; i++) {
						sendVars = sendVars + "&" + encodeURIComponent(tupleList[i][0]) + "=" + encodeURIComponent(tupleList[i][1]);
					}
				} else {
					for(var i=1; i<varslen; i++) {
						sendVars = sendVars + "&" + encodeURIComponent(tupleList[i].name) + "=" + encodeURIComponent(tupleList[i].value);
					}
				}
				
				url = AjaxEngine.appendCacheKillerToURL(url + sendVars);
				
				AjaxEngine.httpReq.open("GET", url, true);
				AjaxEngine.httpReq.send(null);
				AjaxEngine.httpReq.onreadystatechange = AjaxEngine.readyStateChange;
			}
		},
		readyStateChange: function() {
			if(AjaxEngine.httpReq.readyState == 4) {
				if(!AjaxEngine.cancelling) {
					AjaxEngine.callback(AjaxEngine.httpReq.responseText);
				}
				AjaxEngine.busy = false;
				if(AjaxEngine.processQueue.length > 0) {
					var next = AjaxEngine.processQueue.shift();	
					if(next.method == "get") {
						AjaxEngine.get(next.url, next.callback, next.tupleList);
					} else if(next.method == "post") {
						AjaxEngine.post(next.url, next.callback, next.tupleList);
					}
				}
			}
		},
		cancelAllTransfers: function() {
			AjaxEngine.processQueue = new Array();
			AjaxEngine.cancelling = true;
		}
	}
	
	var Tuple = self.Tuple = function(name, value) {
		this.name = name;
		this.value = value;
	}
	
	var checkIsArray = self.checkIsArray = function(obj) {
		return (obj.constructor.toString().indexOf("Array") != -1);
	}
})();
