jQuery.fn.extend({
	formValidate : function(options) {
		var formElements = $("#" + this.attr("id") + " :input");
		$(".formInvalid").remove();
		var emailValue = "";
		var bolError = false;
		var focusField = false;
		formElements.each(function() {
			if( this.id != "AddressLookup" ) {
				this.parentNode.className = this.parentNode.className.replace("formError");
				if( this.disabled != true) {
					if( this.className.match("required") && this.value == "" ) {
						$( this.parentNode ).setFormError("formError", "[ Required ]");
						if(focusField == false) { focusField =  this; }
						bolError = true;
					}
					if( this.type == "checkbox" && this.className.match("required") && this.checked == false ) {
						$( this.parentNode ).setFormError("formError", "");
						if(focusField == false) { focusField =  this; }
						bolError = true;
					}
					
					if( this.name == "email" ) {
						emailValue = this.value;
					}
					if( this.name == "email" && this.value != "" && !$(this).isEmail() ) {
						$( this.parentNode ).setFormError("formError", "[ Invalid ]");
						if(focusField == false) { focusField =  this; }
						bolError = true;
					}
					if( this.name == "emailConfirm" && this.value != emailValue && this.className != "required" ) {
						$( this.parentNode ).setFormError("formError", "[ Does not match ]");
						if(focusField == false) { focusField =  this; }
						bolError = true;
					}
				}
			}
		});
		
		/* Either or check */
		if(options.either) {
			for (var i = 0; i < options.either.length; i++ ) {
				var either = options.either[i];
				if( !either[0].attr("value") && !either[1].attr("value") ) {
					// 1
					$( either[0][0].parentNode ).setFormError("formError", "");
					
					// 2
					$( either[1][0].parentNode ).setFormError("formError", "[ Required ]");
					if(focusField == false) { focusField = either[0][1]; }
					bolError = true;
				}
			}
		}
		
		/* Valid characters check */
		if(options.validChars) {
			var value = "";
			for (elemId in options.validChars) {
				value = $("#" + elemId).val()
				if(value != undefined && value != "") {
					if( options.validChars[elemId].test(value) == false ) {
						$( document.getElementById(elemId).parentNode ).setFormError("formError", "[ Invalid ]");
						if(focusField == false) { focusField =  this; }
						bolError = true;
					}
				}
			}
		}
		
		/* Date of birth check */
		if (options.DoB) {
			var requiredAge = 18;
			var year = parseInt(options.DoB.date.year);
			var month = parseInt(options.DoB.date.month - 1);
			var day = parseInt(options.DoB.date.day);
			
			/* Test if that's a valid date (not 31/2/1985) */
			var testDate = new Date(year, month, day);
			var validDate = day == testDate.getDate() &&  month == testDate.getMonth() && year == testDate.getFullYear();
			
			var DoB = new Date((year + requiredAge), month, day);
			var today = new Date;
			
			if ( ((today.getTime() - DoB.getTime()) < 0) || validDate == false ) {
				var errorMessage = validDate == false ? "[ invalid ]" : "[ Not 18 ]";
				
				$( document.getElementById("dateOfBirth[day]").parentNode ).setFormError("formError", errorMessage);
				if(focusField == false) { focusField =  this; }
				bolError = true;
			}
		}
		if(focusField != false) { focusField.focus(); }
		return !bolError;
	},
	
	setFormError : function(aErrorClassName, aErrorMessage) {
		if ( !this.attr("class") || !this.attr("class").match(aErrorClassName) ) {
			this.addClass(aErrorClassName);
		}
		
		if( this.children("span.formInvalid").length == 0 ) {
			this.append('<span class="formInvalid small">' + aErrorMessage + '</span>');
		}
		
		/* Woa, flash */
		// $(this).fadeTo("fast", 0.5, function() { $(this).fadeTo("fast", 1.0) });
	},
	
	validChars : function(chars) {
		alert(chars);
	},
	
	isEmail : function() {
		var str = this.attr("value");
		var regEmail = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
		if(regEmail.test(str)) {
			return true;
		} else {
			return false;
		}
	}
});