if (Kodiak == undefined) {
	var Kodiak = {
		Global : {},
		UI : {},
		Effects : {}
	};
}

var ie = (navigator.userAgent.search(/MSIE/gi) != -1);

Kodiak.UI.DomFunctions = {
	GetElement : function(targetElement) {
		if (document.getElementById) return (document.getElementById(targetElement));
		else return (document.all[targetElement]);
	},

	GetElementsByTagName : function(tagName) {
		var targets = [], subjects = document.getElementsByTagName(tagName);
		for (var a = 0; a < subjects.length; a++) targets.push(subjects[a]);

		return (targets);
	},

	GetElementsByClassName : function(tagName, className) {
		var targets = [];
		var tags = document.getElementsByTagName(tagName);
		for (var a = 0; a < tags.length; a++) {
			if (tags[a].className == className || tags[a].className.indexOf(className) != -1)
				targets.push(tags[a]);
		}

		return (targets);
	},

	AppendElementStyle : function(target, styleText) {
		var element = (typeof(target) == "string" ? $get(target) : target);
		element.style.cssText += (element.style.cssText.search(/;$/g) == -1 ? "; " : " ") + styleText;
	},

	SetElementStyle : function(target, styleText) {
		var element = (typeof(target) == "string" ? $get(target) : target);
		element.style.cssText = styleText;
	},

	Build : function(buildDom) {
		var domObj = null;

		var buildProperties = Kodiak.UI.DomFunctions.GetProperties(buildDom);
		var subject, actual;
		var attrList, styleList, attr, styles, attrSubj, styleSub, domStyle;
		for (var a = 0; a < buildProperties.length; a++) {
			subject = buildProperties[a];
			actual = buildDom[subject];

			if (subject.search(/(nodeName|tagName)/) != -1) domObj = document.createElement(actual);

			else if (subject.search(/(attr)/) != -1) {
				attrList = Kodiak.UI.DomFunctions.GetProperties(buildDom.attr);
				if (Array.isViable(attrList)) {
					var attr = buildDom.attr;
					var attrSubj;
					for (var i = 0; i < attrList.length; i++) {
						attrSubj = attrList[i];
						if (domObj[attrSubj] != undefined) domObj[attrSubj] = attr[attrSubj];
					}
				}
			} else if (subject.search(/(style)/) != -1) {
				/* Needs work */
				styleList = Kodiak.UI.DomFunctions.GetProperties(buildDom.style);
				if (Array.isViable(styleList)) {
					styles = buildDom.style;

					for (var i = 0; i < attrList.length; i++) {
						styleSub = styleList[i];
						domObj.style[styleSub] = styles[styleSub];
					}
				}
			}
		}

		return (domObj);
	},

	GetProperties : function(obj) {
		var props = [];

		for (var subject in obj) {
			if (typeof(obj[subject]) != "function")
				props.push(subject);
		}

		return (props);
	},

	WireEvent : function(target, eventName, delegate) {
		var actual = (typeof(target) == "string" ? Kodiak.UI.DomFunctions.GetElement(target) : target);

		if (ie) {
			eventName = (eventName.search(/^on/gi) == -1 ? "on" : "") +  eventName;
			actual.attachEvent(eventName, delegate);
		} else {
			eventName = (eventName.search(/^on/gi) != -1 ? eventName.replace(/^on/gi, "") : eventName);
			actual.addEventListener(eventName, delegate, false);
		}
	},

	StripEvent : function(target, delegate) {
		var actual = (typeof(target) == "string" ? Kodiak.UI.DomFunctions.GetElement(target) : target);

		if (ie) {
			eventName = (eventName.search(/^on/gi) == -1 ? "on" : "") +  eventName;
			actual.dettachEvent(eventName, delegate);
		} else {
			eventName = (eventName.search(/^on/gi) != -1 ? eventName.replace(/^on/gi, "") : eventName);
			actual.removeEventListener(eventName, delegate, false);
		}
	},

	GetParentElement : function(target) {
		var actual = (typeof(target) == "string" ? Kodiak.UI.DomFunctions.GetElement(target) : target);
		return (actual.parentNode);
	},

	GetPosition : function(target) {
		var actual = (typeof(target) == "string" ? Kodiak.UI.DomFunctions.GetElement(target) : target);
		var point = { x : 0, y : 0 };

		if (actual.offsetParent) {
			do {
				point.x += actual.offsetLeft;
				point.y += actual.offsetTop;
			} while (actual = actual.offsetParent);
		}

		return (point);
	},

	Import : function(scriptPath) {
		try {
			var x = $xmlhttp("HEAD", scriptPath, false);
			x.send(null);

			if (x.status == 200) {
				var s = $build( { nodeName : "script", attr : { src : scriptPath, type : "text/javascript", language : "javascript" }});
				$getByTag("head")[0].appendChild(s);
			} else {
				throw new Error("Status code other than 200 returned.");
			}
			return (true);
		} catch (e) {
			return (false);
		}
	},

	BuildXmlRequest : function(method, url, async) {
		var x = (ie ? new ActiveXObject("MSXML2.XMLHTTP") : new XMLHttpRequest());
		x.open(method, url, async);
		return (x);
	}
};

/* Aliases */
$get = Kodiak.UI.DomFunctions.GetElement;
$getByTag = Kodiak.UI.DomFunctions.GetElementsByTagName;
$getByClass = Kodiak.UI.DomFunctions.GetElementsByClassName;
$appendStyle = Kodiak.UI.DomFunctions.AppendElementStyle;
$setStyle = Kodiak.UI.DomFunctions.SetElementStyle;
$build = Kodiak.UI.DomFunctions.Build;
$wire = Kodiak.UI.DomFunctions.WireEvent;
$strip = Kodiak.UI.DomFunctions.StripEvent;
$getParent = Kodiak.UI.DomFunctions.GetParentElement;
$position = Kodiak.UI.DomFunctions.GetPosition;
$xmlhttp = Kodiak.UI.DomFunctions.BuildXmlRequest;
$import = Kodiak.UI.DomFunctions.Import;


Kodiak.Global.ArrayExtensions = {
	forEach 	: function(delegate) {
		for (var a = 0; a < this.length; a++)
			delegate.apply(this[a]);
	},

	indexOf 	: function(subject) {
		for (var a = 0; a < this.length; a++) {
			if (this[a] === subject) {
				return (a);
				break;
			}
		}
		return (-1);
	},

	clear		: function(subject) {
		subject = [];
	},

	find		: function(predicate) {
		for (var a = 0; a < this.length; a++) {
			if (predicate.apply(this[a])) {
				return (this[a]);
			}
		}

		return (null);
	},

	findAll		: function(predicate) {
		var result = [];
		for (var a = 0; a < this.length; a++) {
			if (predicate.apply(this[a]))
				result.push(this[a]);
		}
		return (result);
	},

	lastIndexOf	: function(subject) {
		var result = -1;
		for (var a = this.length; a > -1; a--) {
			if (this[a] === subject) {
				result = a;
				break;
			}
		}
		return (result);
	},

	trueForAll	: function(predicate) {
		for (var a = 0; a < this.length; a++) {
			if (!predicate.apply(this[a]))
				return (false);
		}

		return (true);
	},

	isViable : function(subject) {
		return (subject != null && subject instanceof Array && subject.length != 0);
	}
};

Kodiak.Global.StringExtensions = {
	isNullOrEmpty : function (subject) {
		return (subject == null || !(subject instanceof String) || subject.length == 0);
	},

	trim : function() {
		return (this.trimStart().trimEnd());
	},

	trimEnd : function() {
		return (this.replace(/\s+$/g, ""));
	},

	trimStart : function() {
		return (this.replace(/^\s+/g, ""));
	},

	encode : function() {
		return (encodeURIComponent(this.trim()));
	}
};

/* Extensions */
Array.clear = Kodiak.Global.ArrayExtensions.clear;
Array.isViable = Kodiak.Global.ArrayExtensions.isViable;

Array.prototype.forEach = Kodiak.Global.ArrayExtensions.forEach;
Array.prototype.indexOf = Kodiak.Global.ArrayExtensions.indexOf;
Array.prototype.find = Kodiak.Global.ArrayExtensions.find;
Array.prototype.findAll = Kodiak.Global.ArrayExtensions.findAll;
Array.prototype.lastIndexOf = Kodiak.Global.ArrayExtensions.lastIndexOf;
Array.prototype.trueForAll = Kodiak.Global.ArrayExtensions.trueForAll;

String.isNullOrEmpty = Kodiak.Global.StringExtensions.isNullOrEmpty;
String.prototype.trim = Kodiak.Global.StringExtensions.trim;
String.prototype.trimEnd = Kodiak.Global.StringExtensions.trimEnd;
String.prototype.trimStart = Kodiak.Global.StringExtensions.trimStart;
String.prototype.encode = Kodiak.Global.StringExtensions.encode;
