
var doc = document;

/*
	get ALL children of a node, all depths
	var children = document.getElementById('id').getElementsByTagName('*');
*/

var tools = new Toolbox();
var dom = tools.dom;
var browser = tools.browser;


/* *** TOOLBOX OBJECT ************************************************************************** */


function Toolbox () {
	
	var toolbox = this;
	
	this.browser = null;
	this.dom = null;	
	this.queues = [];
	this.trimRegExp = /^\s+|\s+$/g;
	
	
	this.construct = function () {
		this.browser = new this.Browser();
		this.dom = new this.DOM();
		//this.dom.getRoot();  
	};
	
	
	/* *** DOM FUNCS ************************************************************************** */
	
	this.DOM = function () {
		
		//this.root = null;
		this.body = null;
		
		
		this.get = function (id) {
			var e = null;
			if (id) {
				if (typeof(id) == "string") {
					e = this.enhance(doc.getElementById(id));
				}
				else {
					e = this.enhance(id);
				}
			}
			return e;
		};
		
		
		this.getBody = function () {
			if (this.body == null) {
				this.body = this.enhance(doc.body || doc.documentElement);
			}
			return this.body;			
		};
		
	
		this.remove = function (e) {
			e = this.get(e);
			if (e && e.parentNode) {
				var result = e.parentNode.removeChild(e);
			}
			return e;
		};
		
		
		this.enhance = function (e) {
			
			if (e && e.tagName && ! e.css) {

				e.css = new toolbox.CSS(e);
				
				
				e.create = function (tagName, className, id) {
					var newEl = doc.createElement(tagName);
					newEl.setAttribute("id", id);
					newEl.className = className;
					return this.push(newEl);
				};
				
				
				e.createText = function (string) {
					var newEl = doc.createTextNode(string);
					return this.push(newEl);
				};
				
				
				e.getParent = function () {
					return $(this.parent);
				};
				
				
				e.get = function (tagName, cssClass) {
					var els = this.getElementsByTagName(tagName);
					for (var i=0; i < els.length; i++) {
						if (els[i].className.indexOf(cssClass) > -1 || cssClass == null) {
							return $(els[i]);
						}
					}
				};
				
				
				e.getByClassName = function (name) {
					var kids = this.getChildren(true);
					var matches = [];
					
					for (var i=0; i < kids.length; i++) {
						if ($(kids[i]).css.hasClass(name)) {
							matches.push(kids[i]);
						}
					}
					return matches;
				};		
				
				
				e.getChildren = function (deep) {
					if (deep) {
						return this.getElementsByTagName("*");
					}
					else {
						return $(this.childNodes);
					}
				};
				
				
				e.push = function (el) {
					this.appendChild(el);
					return $(el);
				};
				
				
				e.unshift = function (el) {
					if (this.childNodes.length > 0) {
						this.insertBefore(el, this.childNodes[0]);
					}
					else {
						this.push(el);
					}
					return $(el);
				};
				
				
				e.setOpacity = function (percent, steps, delay) {
					if (arguments.length == 1) {
						if (browser.IE) {
							this.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+ (percent/100) +")";
						}
						else {
							this.style.opacity = percent/100;	
						}
						this.css.opacity = percent;
					}
					else {
						var current = this.css.opacity;
						var op = 0;
						var queue = new toolbox.Queue(this.id + "opacity", delay, true);
						for (var i=0; i < steps; i++) {
							queue.push(
								function (el, opac) {
									el.setOpacity(opac);
								},
								[this, current + ((i+1) * ((percent - current)/steps))]
							);
						}
						queue.push(
							function (el) {
								el.setOpacity(percent);
							},
							this
						);
						return queue;
					}
				};
				
	
				e.onEvent = function (evName, action) {
					if (this.addEventListener) {
						this.addEventListener(evName, action, false);
					}
					else if (this.attachEvent) {
						this.attachEvent(evName, action);
					}
				};
				
			}
			
			return e;
		};
	};
	
	
	/* *** CSS FUNCS ************************************************************************** */
	
	this.CSS = function (e) {

		this.e = e;
		this.opacity = 100;
		this.propRegExp = /-(.)/g;
		
		
		this.get = function (p, returnInt) {
			var val;
			
			if (toolbox.browser.IE) {
				if (eval("this.e.currentStyle")) {
					val = eval("this.e.currentStyle." + this.jsProperty(p));
				}
				else {
					val = null;
				}
			}
			else {
				var style = doc.defaultView.getComputedStyle(this.e,"");
				if (style != null) { val = style.getPropertyValue(p); }
			}
			if (p != null && returnInt) {
				val = parseInt(val);
				if (isNaN(val)) { val = 0; }
			}
			return val;
		};
		
		
		this.set = function (p, val) {
			eval("this.e.style." + this.jsProperty(p) + " = '" + val + "'");
		};
		
		
		this.getInt = function (p) {
			return this.get(p, true);
		};
		
		
		this.hasClass = function (c) {
			var test = " " + this.e.className + " ";
			if (test.indexOf(" " + c + " ") > -1) {
				return true;
			}
			return false;
		};
		
		
		this.addClass = function (c) {
			if (!this.hasClass(c)) { 
				if (this.e.className) {
					 this.e.className += " " + c;	
				}
				else {
					this.e.className = c;
				}
			}
		};
		
		
		this.removeClass = function (c) {
			var re = new RegExp(" " + c + " ");
			this.e.className = toolbox.trim((" " + this.e.className + " ").replace(re, ''));
		};

		
		this.toggle = function (prop, a, b) {
			var val = this.get(prop);
			
			if (val == a) {
				this.set(prop, b);
			}
			else {
				this.set(prop, a);
			}
		};		
		
		
		this.jsProperty = function (p) {
			return p.replace(this.propRegExp, 
				function (str, m1) {
					return m1.toUpperCase();
				}
			); 
		};
				
		
	};
	

	/* *** BROWSER FUNCS ************************************************************************** */
	
	
	this.Browser = function () {
	
		this.IE      = false;
		this.MOZILLA = false;
		this.SAFARI  = false;
		this.OPERA   = false;
		this.name    = ""; 
		this.ver     = 0; 
		
		this.construct = function () {
			var appVer = navigator.appVersion;
			var agent = navigator.userAgent;
			if (window.opera) {
				this.OPERA = true;
				this.ver = opera.version();
				this.name = "Opera";
			}
			else if (appVer.indexOf("MSIE") > -1 && document.all) {
				var start = appVer.indexOf("MSIE ") + 5;
				this.IE = true;
				this.ver = parseFloat(appVer.substring(start, appVer.indexOf(";", start)));
				this.name = "Internet Explorer";
			}
			else if (appVer.indexOf("Safari") > -1) {
				var start = appVer.indexOf("AppleWebKit/") + 12;
				this.SAFARI = true;
				this.ver = parseFloat(appVer.substring(start, appVer.indexOf(" (", start)));
				this.name = "Safari";
			}
			else {
				this.MOZILLA = true;
				if (navigator.userAgent.indexOf("Firefox") > -1) {
					this.ver = parseFloat(agent.substring(agent.lastIndexOf("/")+1));
					this.name = "Firefox";
				}
				else {
					var start = agent.indexOf("rv:") + 3;
					this.ver = parseFloat(agent.substring(start, agent.indexOf(")", start)));
					this.name = "Mozilla";
				}
			}
		};


		this.getInnerWidth = function () {
			if (self.innerWidth) {
				return self.innerWidth;
			}
			else if (doc.documentElement && doc.documentElement.clientWidth) {
				return doc.documentElement.clientWidth;
			}			
			else if (doc.body && doc.body.clientWidth) {
				return doc.body.clientWidth;
			}
			return 0;
		};
		
		
		this.getInnerHeight = function () {
			if (window.innerHeight) {
				return window.innerHeight;
			}
			else if (doc.documentElement && doc.documentElement.clientHeight) {
				return doc.documentElement.clientHeight;
			}				
			else if (doc.body && doc.body.clientHeight) {
				return doc.body.clientHeight;
			}
			return 0;
		};
		
		
		this.onEvent = function (evName, action) {
			if (window.addEventListener) {
				window.addEventListener(evName, action, false);
			}
			else if (window.attachEvent) {
				window.attachEvent(evName, action);
			}
		};
		
		
		
		this.stopEvent = function (ev) {
			ev = (ev || window.event);
			if (ev) {
				if (ev.stopPropagation) {
					ev.stopPropagation();
				}
				ev.cancelBubble = true;
			}			
		};
		
		
		this.construct();
	};
	

	/* *** QUEUE FUNCS ************************************************************************** */
	
	this.Queue = function (name, autoAdvance) {
		this.actions = [];
		this.name = name;
		this.autoAdvance = autoAdvance;
		this.timer = null;
	
		var thisQueue = this;
		
		this.push = function (func, args, delay) {
			this.add(func, args, false, delay);
		};
		
		this.unshift = function (func, args, delay) {
			this.add(func, args, true, delay);
		};
		
		this.add = function (func, args, top, delay) {
			if (!args) {
				args = [];	
			}
			else if (!toolbox.isArray(args)) {
				args = [args];
			}
			if (top) {
				this.actions.unshift(new toolbox.QueueAction(func, args, delay));
			}
			else {
				this.actions.push(new toolbox.QueueAction(func, args, delay));
			}
			//console.log("Adding " + func.toString());
			if (this.timer == null && this.autoAdvance) {
				this.next();
			}
		};
		
		this.next = function () {
			this.clearTimeout();
			if (this.actions.length > 0) {
				var action = thisQueue.actions.shift();
				if (action.delay) {
					this.timer = setTimeout(
						function () { 
							action.run();
							delete action;
							if (thisQueue.autoAdvance) {
								thisQueue.next();
							}
						}, 
						action.delay
					);
				}
				else {
					action.run();
				}
			}
		};
		
		this.addPause = function (ms) {
			this.push(function () {true;}, [], ms);
		};
		
		this.stop = function () {
			this.clearTimeout();
			toolbox.queues[name] = null;
		};
		
		this.clearTimeout = function () {
			clearTimeout(this.timer);
			this.timer = null;
		};
		
		if (toolbox.queues[name]) {
			toolbox.queues[name].stop();
		}
		toolbox.queues[name] = this;		
		
	};
	
	
	this.QueueAction = function (func, args, delay) {
		this.func = func;
		this.args = args;
		this.delay = delay ? delay : 1;
		
		this.run = function () {
			this.func.apply(this, args);
			//console.log(this.func.toString());
		};
	};	
	

	/* *** GENERAL-PURPOSE ************************************************************************** */
	
	this.trim = function (str) {
		return str.replace(this.trimRegExp,"");
	};
	
	
	this.repeat = function (string, num) {
		var rString = '';
		for (var i=0; i < num; i++) {
			rString+= string;
		}
		return rString;
	};
	
	this.isArray = function (obj) {
		if (typeof obj == 'object' && obj.length != null && obj.pop) {
			return true;
		}
		return false;
	};

	
	this.construct();
}



/* *** GLOBAL FUNCS ************************************************************************** */


function $ (id) {
	if (tools.isArray(id)) {
		//is an array
		for (var i=0; i < id.length; i++) {
			id[i] = tools.dom.get(id);
		}
		return id;
	}
	else {
		return tools.dom.get(id);
	}
}
