// Removes leading and trailing whitespace from form fields
function trim(el) {
	el.value = el.value.replace(/^\s+|\s+$/g, '');
	return el;
}

// Encapsulates shared functionality by all validation functions; test either a boolean, or a string against
// a RegEx, and if falsy, alert a message and focus on invalid field
function Validate(el, msg, test) {
	trim(el);
	var valid = (typeof test == 'boolean') ? test : test.test(el.value);
	if (!valid) {
		alert(msg);
		if (el) el.focus();
	}
	return valid;
}

// Validate that a date occurs after another date. Dates follow dd[x]mm[x]yyyy format, where [x] equals
// any character whatsoever
function ValidateDateAfterDate(afterDateEl, beforeDateEl, afterDateFieldName, beforeDateFieldName) {
	var afterDate		= new Date();
	var afterDd			= afterDateEl.value.substring(0,2);
	var afterMm			= afterDateEl.value.substring(3,5);
	var afterYyyy		= afterDateEl.value.substring(6);
	var beforeDate	= new Date();
	var beforeDd		= beforeDateEl.value.substring(0,2);
	var beforeMm		= beforeDateEl.value.substring(3,5);
	var beforeYyyy	= beforeDateEl.value.substring(6);
	var msg;
	var valid = true;

	afterDate.setFullYear(	afterYyyy,	afterMm - 1,	afterDd);
	beforeDate.setFullYear(	beforeYyyy,	beforeMm - 1,	beforeDd);

	if (afterDate <= beforeDate) {
		valid	= false;
		msg		= 'Please enter a ' + afterDateFieldName + ' which occurs after the ' + beforeDateFieldName;
	}
	return Validate(afterDateEl, msg, valid);
}

// Validate a date in the format dd/mm/yyyy
function ValidateDdMmYyyyDate(el, fieldName, message) {
	var valid = true, msg;
	if (/^(0[1-9]|1[0-9]|2[0-9]|3[01])\/(0[1-9]|1[012])\/([0-9][0-9][0-9][0-9])$/.test(el.value)) {
		var dd		= el.value.substring(0,2);
		var mm		= el.value.substring(3,5);
		var yyyy	= el.value.substring(6);

		// 31st of a month with 30 days
		if (dd == 31 && (mm == 4 || mm == 6 || mm == 9 || mm == 11)) {
			var month;
			switch (mm) {
				case 4:		month = 'April';			break;
				case 6:		month = 'June';				break;
				case 9:		month = 'September';	break;
				case 11:	month = 'November';		break;
			}
      valid	= false;
			msg		= 'You have entered a day of the 31st. ' + month + ' has only 30 days; please enter a ' +
							'valid date';
    }
		// February 30th or 31st
		else if (dd >= 30 && mm == 2) { 
			day		= (dd == 30) ? dd + 'th' : dd + 'st';
      valid = false;
			msg		= 'You have entered a day of the ' + day + '. February has only 28 days, or 29 days on ' +
							'a leap year; please enter a valid date';
    }
		// February 29th outside a leap year
		else if (mm == 2 && dd == 29 && !(yyyy % 4 == 0 && (yyyy % 100 != 0 || yyyy % 400 == 0))) {
      valid = false;
			msg		=	'You have entered a day of the 29th and a month of February. ' + yyyy + ' is not a ' +
							'leap year, so February has only 28 days; please enter a valid date';
    }
	}
	else {
		valid = false;
		msg		= 'Please enter a valid ' + fieldName;
	}
	return Validate(el, message || msg, valid);
}

// Validate the format of an email address. Regex includes all TLDs as of Q2 2008
function ValidateEmail(el, msg) {
	var regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*\.(\w{2}|(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum))$/;
	var msg = msg || 'The email address you have entered is invalid.\nIt should resemble \'name@company.com\'';
	return Validate(el, msg, regex);
}

// Validate the format of a telephone number
function ValidateTelephoneNumber(el, msg) {
	return Validate(el, msg, /^[\d ()\+]+$/);
}

// Validate the existence of a value that isn't whitespace
function ValidateSubstance(el, msg) {
	return Validate(el, msg, (el.value !== ''));
}
