/* #############################################################################

NS: TESCO
	static: yes
NS: TESCO.system.browser
	static: yes

dependancies:
	none

############################################################################# */

var TESCO = {
	VERSION : "1.0.0",
	NAME : "TESCO",
	
	system : {
		DOM : {}
	},
	app : {},
	lib : {}
}

TESCO.ns = function(namespace) {
	if(namespace) {
		var obj = TESCO;
		var parts = namespace.split(".");
		for(var i = 0; i < parts.length; i++) {
			if(!obj[parts[i]]) {
				obj[parts[i]] = {};
			}
			obj = obj[parts[i]];
		}
		return obj;
	}
}

// *** IMPORTANT *** TESCO.system.browser must be handled with care... Only use as a very last resort!
TESCO.system.browser = new function() {
	this.VERSION = "1.0.1";
	this.NAME = "TESCO.system.browser";

	this.isSafari = (navigator.userAgent.match(/safari/gi) != null);
	this.isOpera = (navigator.userAgent.match(/opera/gi) != null);
	this.isIE = (!this.isSafari && !this.isOpera && (navigator.userAgent.match(/msie/gi) != null));
	this.isMac = (navigator.userAgent.match(/mac/gi) != null);
	this.isMacIE = (this.isMac && this.isIE);
}

Number.prototype.format = function(decimalPlaces, thousands) {
	var ret = this;
	if(this.toFixed) {
		ret = this.toFixed(decimalPlaces);
	} else {
		if(decimalPlaces == 0) {
			ret = Math.round(this);
		} else {
			var i = Math.pow(10, decimalPlaces);
			var s = new String(Math.round(this * i) / i);
			for(var ii = 0; ii < decimalPlaces - (s.length - s.indexOf(".") - 1); ii++) {
				s += "0";
			}
			ret = s;
		}
	}
	
	if(thousands) {
		var dp = ret.indexOf(".");
		if(dp != -1) {
			var iN = ret.substr(0, dp);
			var sRet = "", len, pos;
			for(var i = iN.length - 3; i > -3; i-=3) {
				if(i < 0) {
					len = 3 + i;
					pos = 0;
				} else {
					len = 3;
					pos = i;
				}
				sRet = ((pos > 0 ? "," : "") + iN.substr(pos, len)) + sRet;
			}
			ret = sRet + ret.substr(dp);
		}
	}
	
	return ret;
}

String.prototype.rtrim = function() {
	return this.replace(/\s*$/,"");
}

String.prototype.ltrim = function() {
	return this.replace(/^\s*/,"");
}

String.prototype.trim = function() {
	return this.ltrim().rtrim();
}

String.prototype.capitaliseFirstWord = function() {
	return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}

String.prototype.URLEncode = function() {
	var SAFECHARS = "0123456789" +					// Numeric
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +			// Alphabetic
		"abcdefghijklmnopqrstuvwxyz" +
		"-_.!~*'()";											// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";
	
	var encoded = "";
	for (var i = 0; i < this.length; i++ ) {
		var ch = this.charAt(i);
		if(ch == " ") {
			encoded += "+";								// x-www-urlencoded, rather than %20
		} else if(SAFECHARS.indexOf(ch) != -1) {
			encoded += ch;
		} else {
			var charCode = ch.charCodeAt(0);
			if(charCode > 255) {
				// Unicode Characters cannot be encoded using standard URL encoding (URL encoding only supports 8-bit characters)
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	}
	
	return encoded;
}

String.prototype.URLDecode = function() {
	// Replace + with ' ', %xx with equivalent character and put [ERROR] in output if %xx is invalid.
	var HEXCHARS = "0123456789ABCDEFabcdef"; 
	var plaintext = "";
	var i = 0;
	while(i < this.length) {
		var ch = this.charAt(i);
		if(ch == "+") {
			plaintext += " ";
			i++;
		} else if(ch == "%") {
			if (i < (this.length-2) 
						&& HEXCHARS.indexOf(this.charAt(i+1)) != -1 
						&& HEXCHARS.indexOf(this.charAt(i+2)) != -1) {
				plaintext += unescape( this.substr(i,3) );
				i += 3;
			} else {
				plaintext += "%[ERROR]";
				i++;
			}
		} else {
			plaintext += ch;
			i++;
		}
	}
	
	return plaintext;
}

String.prototype.format = function() {
	var s = this;
	for(var i = 0; i < arguments.length; i++) {
		s = s.replace("{" + i + "}", arguments[i]);
	}
	return s;
}

if(!Array.prototype.splice) {
	Array.prototype.splice = function(index, delTotal) {
		var temp = [];
		var response = [];
		var A_s = 0;
		for (A_s = 0; A_s < index; A_s++) {
			temp[temp.length] = this[A_s];
		}
		for (A_s = 2; A_s < arguments.length; A_s++) {
			temp[temp.length] = arguments[A_s];
		}
		for (A_s = index + delTotal; A_s < this.length; A_s++) {
			temp[temp.length] = this[A_s];
		}
		for (A_s = 0; A_s < delTotal; A_s++) {
			response[A_s] = this[index + A_s];
		}
		this.length = 0
		for (A_s = 0; A_s < temp.length; A_s++) {
			this[this.length] = temp[A_s];
		}
		return response;
	}
}

if(!Array.prototype.pop) {
	Array.prototype.pop = function() {
		var s;
		if(this.length > 0) {
			s = this[this.length - 1];
			this.length = this.length - 1;
		}
		return s;
	}
}

if(!Array.prototype.push) {
	Array.prototype.push = function(o) {
		this[this.length] = o;
		return o;
	}
}

if(!Array.prototype.unshift) {
	Array.prototype.unshift = function() {
		if(arguments.length > 0) {
			for(var i = this.length - 1; i >= 0; i--) {
				this[i + arguments.length] = this[i];
			}
			for(var i = 0; i < arguments.length; i++) {
				this[i] = arguments[i];
			}
		}
		return this.length;
	}
}

Array.prototype["#isArray"] = true;

Object.prototype.copyInto = function(to, deep) {
	_copyInto(this, to, deep);
	
	function _copyInto(from, to, deep) {
		if(from && to) {
			for(var i in from) {
				if(deep && typeof from[i] == "object") {
					_copyInto(from[i], to[i], deep);
				} else if (typeof from[i] != "function"){
					to[i] = from[i];
				}
			}
		}
	}
}

Object.prototype.clone = function(deep) {
	var objectClone = new this.constructor();
	for(var property in this) {
		if(!deep) {
			objectClone[property] = this[property];
		} else if(typeof this[property] == "object") {
			objectClone[property] = this[property].clone(deep);
		} else {
			objectClone[property] = this[property];
		}
	}
	return objectClone;
}

