/**
 * @projectDescription Helper functions
 * @author Jerome Wilson
 */

// *** Strings ***

var DateText = {
	"month_0"		: "January",
	"month_1"		: "February",
	"month_2"		: "March",
	"month_3"		: "April",
	"month_4"		: "May",
	"month_5"		: "June",
	"month_6"		: "July",
	"month_7"		: "August",
	"month_8"		: "September",
	"month_9"		: "October",
	"month_10"		: "November",
	"month_11"		: "December",
	
	"weekday_0"		: "Sunday",
	"weekday_1"		: "Monday",
	"weekday_2"		: "Tuesday",
	"weekday_3"		: "Wednesday",
	"weekday_4"		: "Thursday",
	"weekday_5"		: "Friday",
	"weekday_6"		: "Saturday"	
};


// *** Helper Functions ***

// *** Date

var DateHelper = {

	"dayName": function(dayOfWeekNumber) {
		return DateText["weekday_" + dayOfWeekNumber];
	},

	"monthName": function(monthNumber) {
		return DateText["month_" + monthNumber];
	},
	
	"diff": function(dateFrom, dateTo, units) {
		switch (units) {
			case "m": // months
				return ((dateTo.getFullYear() - dateFrom.getFullYear()) * 12) + (dateTo.getMonth() - dateFrom.getMonth());
			case "y": // years
				return dateTo.getFullYear() - dateFrom.getFullYear();
			case "h": // hours
				return Math.round((dateTo.valueOf() - dateFrom.valueOf()) / 3600000);
			case "n": // minutes
				return Math.round((dateTo.valueOf() - dateFrom.valueOf()) / 60000);
			case "s": // seconds
				return Math.round((dateTo.valueOf() - dateFrom.valueOf()) / 1000);
			default: // days
				return Math.round((dateTo.valueOf() - dateFrom.valueOf()) / 86400000);
		}
	},

	"add": function(refDate, delta, units) {
		var newDate = new Date(refDate);
		switch (units) {
			case "m": // months
				newDate.setMonth(newDate.getMonth() + delta);
			case "y": // years
				newDate.setFullYear(newDate.getFullYear() + delta);
			case "h": // hours
				newDate.setHours(newDate.getHours() + delta);
			case "n": // minutes
				newDate.setMinutes(newDate.getMinutes() + delta);
			case "s": // seconds
				newDate.setSeconds(newDate.getSeconds() + delta);
			default: // days
				newDate.setDate(newDate.getDate() + delta);
		}
		return newDate;
	},

	"format": function(date, format) {
	    return format.replace(/(yyyy|yy|mmmm|mmm|mm|dddd|ddd|dd|d|hh|nn|ss|a\/p|\^)/gi,
	        function($1) {
	            switch ($1.toLowerCase()) {
		            case 'yyyy': return date.getFullYear();
		            case 'yy':	 return date.getFullYear().toString().substr(2, 2);
					case 'mmmm': return DateHelper.monthName(date.getMonth());
		            case 'mmm':  return DateHelper.monthName(date.getMonth()).substr(0, 3);
		            case 'mm':   return (date.getMonth() + 1).padLeft(2, '0');
		            case 'dddd': return DateHelper.dayName(date.getDay());
		            case 'ddd':  return DateHelper.dayName(date.getDay()).substr(0, 3);
		            case 'dd':   return date.getDate().padLeft(2, '0');
		            case 'd':	 return date.getDate();
		            case 'hh':   return ((h = date.getHours() % 12) ? h : 12).padLeft(2, '0');
		            case 'nn':   return date.getMinutes().padLeft(2, '0');
		            case 'ss':   return date.getSeconds().padLeft(2, '0');
		            case 'a/p':  return date.getHours() < 12 ? 'a' : 'p';
					case '^':  
					    switch (date.getDate())
					        {
					        case 1:
					        case 21:
					        case 31:
					            return "st";
					        case 2:
					        case 22:
					            return "nd";
					        case 3:
					        case 23:
					            return "rd";
					        default:
					            return "th";
					        }
				}
	        }
	    );
	},
	
	"isBefore": function(date1, date2) {
		return (date1.valueOf() < date2.valueOf());
	},
	
	"isAfter": function(date1, date2) {
		return (date1.valueOf() > date2.valueOf());
	},
	
	"isEqual": function(date1, date2) {
		return (date1.valueOf() == date2.valueOf());
	},
	
	"earliest": function(date1, date2) {
		var result = null;
		
		for (var i = 0; i < arguments.length; i++) {
			if (!result || (typeof(arguments[i]) != "undefined" && arguments[i].isBefore(result))) {
				result = arguments[i];
			}
		}
		return result;
	},
	
	"latest": function(date1, date2) {
		var result = null;
		
		for (var i = 0; i < arguments.length; i++) {
			if (!result || (typeof(arguments[i]) != "undefined" && arguments[i].isAfter(result))) {
				result = arguments[i];
			}
		}
		return result;
	}
	
};

Date.prototype.monthName = function() {
	return DateHelper.monthName(this.getMonth());
};

Date.prototype.dayName = function() {
	return DateHelper.dayName(this.getDay());
};

Date.prototype.diff = function(comparisonDate, units) {
	return DateHelper.diff(this, comparisonDate, units);
};

Date.prototype.add = function(delta, units) {
	return DateHelper.add(this, delta, units);
};

Date.prototype.format = function(format) {
	return DateHelper.format(this, format);
};

Date.prototype.isBefore = function(compareDate) {
	return DateHelper.isBefore(this, compareDate);
};

Date.prototype.isAfter = function(compareDate) {
	return DateHelper.isAfter(this, compareDate);
};

Date.prototype.isEqual = function(compareDate) {
	return DateHelper.isBefore(this, compareDate);
};

Date.prototype.earliest = function(date1, date2, date3) {
	return DateHelper.earliest(this, date1, date2, date3);
};

Date.prototype.latest = function(date1, date2, date3) {
	return DateHelper.latest(this, date1, date2, date3);
};


// *** String

String.prototype.format = function(text1, text2, text3) {
	var result = String(this);
	
	for (var i = 0; i < arguments.length; i++) {
		result = result.replace(new RegExp("\\{" + i + "\\}"), arguments[i]);
	}
	result = result.replace(/\{\d\}/g, "");
	return result;
};

String.prototype.startsWith = function(text) {
	return (this.length >= text.length && this.substring(0, text.length) == text);
};

String.prototype.endsWith = function(text) {
	return (this.length >= text.length && this.substring(this.length - text.length) == text);
};

String.prototype.padLeft = function(num, character) {
	var padded = String(this);
	
	while (padded.length < num) {
		padded = character + padded;
	}
	return padded.substr(0, num);
};

String.prototype.padRight = function(num, character) {
	var padded = String(this);
	
	while (padded.length < num) {
		padded += character;
	}
	return padded.substr(0, num);
};


// *** Number ***

Number.prototype.padLeft = function(num, character) {
	return this.toString().padLeft(num, character);
};

Number.prototype.padRight = function(num, character) {
	return this.toString().padRight(num, character);
};

Number.prototype.toDecimals=function(n){
	n=(isNaN(n))?2:n;
	var	nT=Math.pow(10,n);
	
	function pad(s){
		s=s||'.';
		return (s.length>n)?s:pad(s+'0');
	}
	return (isNaN(this))?this:((Math.round(this*nT)/nT)).toString().replace(/(\.\d*)?$/,pad);
};


// *** StringBuilder

function StringBuilder(initText) {
	this.sbText = [];
	
	if (initText && initText.length > 0) {
		this.sbText.push(initText);
	}
}

StringBuilder.prototype.append = function(text1, text2, text3, text4, text5) {
	this.sbText.push(text1, text2, text3, text4, text5);
	for (var i = 5; i < arguments.length; i++) {
		this.sbText.push(arguments[i]);
	}
	return this;
};

StringBuilder.prototype.appendFormat = function(format, var1, var2, var3) {
	var result = String(format);
	
	for (var i = 1; i < arguments.length; i++) {
		result = result.replace(new RegExp("\\{" + (i - 1) + "\\}"), String(arguments[i]));
	}
	result = result.replace(/\{\d\}/g, "");
	this.sbText.push(result);
	return this;
};

StringBuilder.prototype.clear = function() {
	this.sbText = [];
	return this;
};

StringBuilder.prototype.toString = function() {
	return this.sbText.join("");
};

StringBuilder.prototype.join = function(stringBuilderToJoin) {
	this.sbText = this.sbText.concat(stringBuilderToJoin.sbText);
	return this;
};

StringBuilder.prototype.replace = function(oldText, newText, caseSensitive) {
	var regEx = new RegExp(oldText,'g' + (caseSensitive ? '' : 'i'));
	return new StringBuilder(this.sbText.join('').replace(regEx, newText));
};


// *** Localized Text ***

var LocalText = {
	
	"get": function(textKey, textStore) {
		var localText = "";
		var locale = (navigator ? (navigator.userLanguage || navigator.language || "en") : "en").toLowerCase();
		var localePrimary = locale.split("-")[0];
		
		if (!textStore) {
			throw("LocalText.get('" + textKey + "') - Error: No text store specified and no default set");
		}
		if (textStore[locale]) {
			localText = (textStore[locale])[textKey];
			if (!localText && textKey.indexOf("__") > -1) { // remove any prefix to see if we have a fallback for this language
				localText = (textStore[locale])[textKey.replace(/\w+__/gi, "")];
			}
		}
		if (!localText && localePrimary != locale && textStore[localePrimary]) {
			localText = (textStore[localePrimary])[textKey];
			if (!localText && textKey.indexOf("__") > -1) { // remove any prefix to see if we have a fallback for this language
				localText = (textStore[localePrimary])[textKey.replace(/\w+__/gi, "")];
			}
		}
		if (!localText) {
			localText = textKey;
		}
		return localText;
	}
	
};


// *** Browser Helpers ***

var Browser = {
	
	"findPos": function(obj) {
		var curleft = 0, curtop = 0;
		if (obj.offsetParent) {
			curleft = obj.offsetLeft;
			curtop = obj.offsetTop;
			while (obj = obj.offsetParent) {
				curleft += obj.offsetLeft
				curtop += obj.offsetTop
			}
		}
		return { "left": curleft, "top": curtop };
	},

	"cancelBubble": function(e) {
		if (!e) e = window.event;
		e.cancelBubble = true;
		if (e.stopPropagation)
			e.stopPropagation();
	},

	"onDomReady": function(funcToCall) {
		if (document.addEventListener) {
            document.addEventListener("DOMContentLoaded", funcToCall, false);
        } else {
            document.write("<scr" + "ipt id='__ieinit' defer='true' " + "src='//:'><\/script>");
            var script = document.getElementById("__ieinit");
            script.onreadystatechange = function() {
                if (this.readyState != "complete") return;
                this.parentNode.removeChild(this);
                funcToCall();
            }
            script = null;
        }
	}

}



