Object.extend(String.prototype, {
	isBlank: function() {
		return /^ *$/.test(this);
	},
	
	trim: function() {
		return this.replace(/(^ +| +$)/g, "");
	},
	
	isNumeric: function() {
		//blank strings are always considered valid
		return this == "" || /^-?([0-9]+(\.[0-9]+){0,1}|\.[0-9]+)$/.test(this);
	},
	
	isEmail: function() {
		//blank strings are always considered valid
		return this == "" || /^([a-zA-Z0-9_\.\-])+\@([a-zA-Z0-9.\-])+(\.[a-zA-Z0-9]{2,4})+$/.test(this);
	},
	
	//used to encode a string for use in a regular expression.
	//this is useful for the string.replace method, since the first
	//argument normally takes a RegExp object.
	regexEncode: function() {
		return this.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
	},
	
	htmlEncode: function() {
		return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
	},
	
	createDate: function(){
		var dateParts = this.split("/");
		var month = parseInt(dateParts[0], 10);
		var day = parseInt(dateParts[1], 10);
		var year = parseInt(dateParts[2], 10);
		
		return new Date(year, month - 1, day, 0, 0, 0, 1);
	},
	
	isDate: function()
	{	
		//blank strings are always considered valid
		if (this == "")
		{
			return true;
		}
		
		//mm/dd/yyyy
		var pattern = /^(1[0-2]|0?[1-9])\/(0?[1-9]|[12][0-9]|3[01])\/(\d\d\d\d)$/;
		
		if (!pattern.test(this))
		{
			return false;
		}
		
		var dateParts = this.split("/");
		var month = parseInt(dateParts[0], 10);
		var day = parseInt(dateParts[1], 10);
		var year = parseInt(dateParts[2], 10);
		
		if (!IsDateValid(month, day, year))
		{
			return false;
		}
		
		return true;
	}
});

Object.extend(Date.prototype, {
	daysBetween: function (dateToCompare) {
	    var difference =
    	    Date.UTC(dateToCompare.getFullYear(), dateToCompare.getMonth(), dateToCompare.getDate(), 0, 0, 0)
	      - Date.UTC(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
	  
	    return Math.floor(Math.abs(difference / 1000 / 60 / 60 / 24));
	},
	
	toShortDateString: function() {
		return (this.getMonth() + 1).toString() + "/" + this.getDate().toString()  + "/" + this.getFullYear().toString();
	},
	
	isWeekend: function() {
		return this.getDay() == 0 || this.getDay() == 6;
	},
	
	add: function(value, unit) {
		
		unit = unit.toLowerCase();
		
		switch (unit)
		{
			case "y":
				return new Date(this.getFullYear() + value, this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds());
			case "m":
				return new Date(this.getFullYear(), this.getMonth() + value, this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds());
			case "d":
				return new Date(this.getFullYear(), this.getMonth(), this.getDate() + value, this.getHours(), this.getMinutes(), this.getSeconds());			
			case "h":
				return new Date(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours() + value, this.getMinutes(), this.getSeconds());
			case "n":
				return new Date(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes() + value, this.getSeconds());
			case "s":
				return new Date(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds() + value);
			default:
				return null;
		}
	}
});

function IsDateValid(month, day, year)
{
	if (month.toString().isBlank() 
		|| day.toString().isBlank() 
		|| year.toString().isBlank()
		|| !month.toString().isNumeric() 
		|| !day.toString().isNumeric() 
		|| !year.toString().isNumeric() 
		|| month.toString().indexOf(".") != -1
		|| day.toString().indexOf(".") != -1
		|| year.toString().indexOf(".") != -1
		|| year.toString().length != 4)
	{
		return false;
	}
	
	var date = new Date(year, month - 1, day, 0, 0, 0, 1);
	return date.getMonth() + 1 == month && date.getDate() == day && date.getFullYear() == year;
}

Object.extend(Number.prototype, {
	numberFormat: function() {
		var parts = this.toString().split(".");
		var number = "";
		
		for (var i = parts[0].length - 1; i >= 0; i--)
		{		
			if ((parts[0].length - i) % 3 == 0 && i > 0)
			{
				number =  "," + parts[0].charAt(i) + number;
			}
			else
			{
				number = parts[0].charAt(i) + number;
			}
		}
		
		if (parts.length > 1)
		{
			number += "." + parts[1];
		}
		
		return number;
	}
});

//wrappers for pretty dialogs
function alertDialog(text, okCallback) {
	Dialog.alert(text, {
		onOk: okCallback || false, 
		okLabel: "OK", 
		windowParameters: {
			className: "alphacube", 
			effectOptions: {
				duration: .25
			} 
		} 
	}); 
};

function confirmDialog(text, okCallback, cancelCallback, okLabel, cancelLabel, windowParameters) {
	Dialog.confirm(text, {
		onOk: okCallback,
		okLabel: okLabel || "OK",
		cancelLabel: cancelLabel || "Cancel",
		onCancel: cancelCallback, 
		windowParameters: Object.extend({
			className: "alphacube",
			effectOptions: {
				duration: .25 
			}
		}, windowParameters || {})
	});
}

function contentDialog(element, options)
{
	element = $(element);
	
	//we preload all the alphacube images so FireFox can cope better
	//when a page is posted immediately after showing the content dialog
	var preloads = $A(['bottom-left-c.gif', 'bottom-middle.gif', 'bottom-right-c.gif', 'button-close-focus.gif', 'button-max-focus.gif', 'button-min-focus.gif', 'frame-left.gif', 'frame-right.gif', 'left-top.gif', 'right-top.gif', 'top-middle.gif']);
	
	preloads.each(function(preload) {
		var img = new Image(100, 100);
		img.src = '/Style/Window/alphacube/' + preload;
	});
	
	options = Object.extend({
		className: "alphacube",
		effectOptions: {
				duration: .25 
		},
		destroyOnClose: true,
		modal: false
	}, options || {});
	
	var w = new Window("win", options);	
	w.setContent(element, true, true);
	
	if (options.width)
	{
		w.setSize(options.width, w.getSize().height);
	}
	
	if (options.height)
	{
		w.setSize(w.getSize().width, options.height);
	}
	
	w.toFront(); 
	w.showCenter(options.modal); 
	
	return w;
}

//binds a date picker to a form element
//requires /Style/fastDatePicker.css and /JavaScript/fastDatePicker.js
function bindDatePicker(elementName) {
	
		var element = $(elementName);
		var a = Element.extend(document.createElement("a"));
		a.href = "#";
		a.update("<img src=\"/Images/calendar.png\" align=\"bottom\" hspace=\"5\" />");
		a.title = "Select Date";

		Event.observe(a, "click", function(evt) {
			var existingCalendar = $(element.id + "_cal");
						
			//if we already have the calendar showing, hide it
			if (existingCalendar)
			{
				existingCalendar.remove();
				return;
			}
	
			//create the div to hold the calendar
			var container = Element.extend(document.createElement("div"));
			var position = Position.cumulativeOffset(element);
			var dimensions = element.getDimensions();
			
			container.id = element.id + "_cal";
			
			//set up the position of the div
			container.setStyle({
				position: "absolute",
				backgroundColor: "#FFFFFF",
				left: position[0] + "px",
				top: (position[1] + dimensions.height) + "px"
			});
			
			//create the date picker
			var picker = new FastDatePicker();
			
			//wire it up so that when a date is picked, the element we're binding 
			//to gets the date in mm/dd/yyyy format
			picker.handleSelection = function dr_SelectDate(container, picker) {
				this.value = picker.date.toShortDateString();
				container.remove();
			}.bind(element, container, picker);
			
			//don't put a restriction on the dates they can pick
			picker.firstSelectableDate = null;
			
			//if the field already has a date in it, let's tell the date picker
			//to default to that date
			if (!element.value.isBlank() && element.value.isDate())
			{
				picker.date = new Date(Date.parse(element.value));
				picker.selectedDate = new Date(picker.date);
			}
			
			//add the picker and container to the document
			container.appendChild(picker.calendar());
			element.up().appendChild(container);
			
			Event.stop(evt);
		});
		
		//add the a tag after the element
		if (!element.nextSibling)
		{
			element.up().appendChild(a);
		}
		else
		{
			element.up().insertBefore(a, element.nextSibling);
		}
};
