function BaseValidator()
{
	this.Form = null;
	this.Name = null;
	this.Label = null;
	this.Message = null;
	this.IsValid = false;
}

function IsNotEmptyValidator(label, message, input)
{
	this.Name = "IsNotEmptyValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" cannot be empty.";
	this.Input = UtilityParseInput(input);
	this.Validate = function()
	{
		this.Input.value = UtilityTrim(this.Input.value);
		this.IsValid = (this.Input.value.length > 0);
	}
}
IsNotEmptyValidator.prototype = new BaseValidator;

function IsOneNotEmptyValidator(label, message, inputArray)
{
	this.Name = "IsOneNotEmptyValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" - at least one cannot be empty.";
	this.Inputs = new Array();
	for (var i=0; i<inputArray.length; i++)
	{
		this.Inputs[this.Inputs.length] = UtilityParseInput(inputArray[i]);
	}
	this.Validate = function()
	{
		for (var i=0; i<this.Inputs.length; i++)
		{
			this.Inputs[i].value = UtilityTrim(this.Inputs[i].value);
			if (this.IsValid == false)
			{
				this.IsValid = (this.Inputs[i].value.length > 0);
			}
		}
	}
}
IsOneNotEmptyValidator.prototype = new BaseValidator;

function IsCheckedValidator(label, message, input)
{
	this.Name = "IsCheckedValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" cannot be empty.";
	this.Input = UtilityParseInput(input);
	this.Validate = function()
	{
		this.IsValid = this.Input.checked;
	}
}
IsCheckedValidator.prototype = new BaseValidator;

function IsOneCheckedValidator(label, message, inputArray)
{
	this.Name = "IsOneCheckedValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" - at least one must be checked.";
	this.Inputs = new Array();
	for (var i=0; i<inputArray.length; i++)
	{
		this.Inputs[this.Inputs.length] = UtilityParseInput(inputArray[i]);
	}
	this.Validate = function()
	{
		for (var i=0; i<this.Inputs.length; i++)
		{
			if (this.IsValid == false)
			{
				this.IsValid = (this.Inputs[i].checked);
			}
		}
	}
}
IsOneCheckedValidator.prototype = new BaseValidator;

function IsValidEmailAddressValidator(label, message, input)
{
	this.Name = "IsValidEmailAddressValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" must be a valid email address (e.g. address@server.com).";
	this.Input = UtilityParseInput(input);
	this.Validate = function()
	{
		this.Input.value = UtilityTrim(this.Input.value);
		var regex = /^[A-Za-z/-9!#-'*+\-/=?_`{-~^]([A-Za-z.-9!#-'*+\-/=?_`{-~^]*[A-Za-z/-9!#-'*+\-/=?_`{-~^])?@([-A-Za-z0-9]+\.)+[A-Za-z0-9]+\.?$/;
		this.IsValid = regex.test(this.Input.value);
	}
}
IsValidEmailAddressValidator.prototype = new BaseValidator;

function FormatValidator(label, message, input, format)
{
	this.Name = "FormatValidator";
	this.Label = label;
	this.Message = (UtilityTrim(message).length > 0) ? message : "\"" + label + "\" is not in a valid format.";
	this.Input = UtilityParseInput(input);
	this.Validate = function()
	{
		this.Input.value = UtilityTrim(this.Input.value);
		this.IsValid = true;
		if (this.Input.value.length != format.length)
		{
			this.IsValid = false;
		}
		else
		{
			for (var i=0; i<format.length; i++)
			{
				var charCode = this.Input.value.charCodeAt(i);
				switch (format.charAt(i))
				{
					case "n": // Any number
					{
						this.IsValid = (charCode >= 48 && charCode <= 57);
						break;
					}
					case "a": // Any lowercase ASCII letter
					{
						this.IsValid = (charCode >= 97 && charCode <= 122);
						break;
					}
					case "A": // Any uppercase ASCII letter
					{
						this.IsValid = (charCode >= 65 && charCode <= 90);
						break;
					}
					case "x": // Any lowercase ASCII letter or number
					{
						this.IsValid = ((charCode >= 48 && charCode <= 57) || (charCode >= 97 && charCode <= 122));
						break;
					}
					case "X": // Any uppercase ASCII letter or number
					{
						this.IsValid = ((charCode >= 48 && charCode <= 57) || (charCode >= 65 && charCode <= 90));
						break;
					}
					case "z": // Any ASCII letter or number
					{
						this.IsValid = ((charCode >= 48 && charCode <= 57) || (charCode >= 97 && charCode <= 122) || (charCode >= 65 && charCode <= 90));
						break;
					}
				}
				if (this.IsValid == false) break;
			}
		}
	}
}
FormatValidator.prototype = new BaseValidator;

function CustomValidator(message, input)
{
	this.Name = "CustomValidator";
	this.Message = message;
	this.Input = UtilityParseInput(input);
	this.Validate = function()
	{
		this.IsValid = false;
	}
}
CustomValidator.prototype = new BaseValidator;


function FormValidator(formRef)
{
	var form = UtilityParseForm(formRef);
	this.ActionColour = "#CCC";
	this.Validators = new Array();
	this.IsValid = true;
	this.ValidationMessage = "";
	this.Add = function(validator)
	{
		validator.Form = form;
		this.Validators[this.Validators.length] = validator;
	}
	this.Validate = function()
	{
		var focused = false;
		for (var i=0; i<this.Validators.length; i++)
		{
			if (this.Validators[i].Input)
			{
				this.Validators[i].Input.style.backgroundColor = "";
			}
			else if (this.Validators[i].Inputs)
			{
				for (var j=0; j<this.Validators[i].Inputs.length; j++)
				{
					this.Validators[i].Inputs[j].style.backgroundColor = "";
				}
			}
			this.Validators[i].Validate();
			if (this.Validators[i].IsValid == false)
			{
				if (this.IsValid) this.IsValid = false;
				this.ValidationMessage += " - " + this.Validators[i].Message + "\n";
				if (!focused)
				{
					if (this.Validators[i].Input && this.Validators[i].Input.focus) this.Validators[i].Input.focus();
					else if (this.Validators[i].Inputs && this.Validators[i].Inputs.length && this.Validators[i].Inputs[0].focus) this.Validators[i].Inputs[0].focus();
					focused = true;
				}
				if (this.Validators[i].Input)
				{
					this.Validators[i].Input.style.backgroundColor = this.ActionColour;
				}
				else if (this.Validators[i].Inputs)
				{
					for (var j=0; j<this.Validators[i].Inputs.length; j++)
					{
						this.Validators[i].Inputs[j].style.backgroundColor = this.ActionColour;
					}
				}
			}
		}
		if (this.ValidationMessage != null && UtilityTrim(this.ValidationMessage).length > 0)
		{
			this.ValidationMessage = "There were problems with the form submission:\n\n" + this.ValidationMessage;
			return false;
		}
		else
		{
			return true;
		}
	}
}

function UtilityParseForm(formRef)
{
	var form = null;
	if (!formRef)
	{
		form = document.forms[0];
	}
	else if (typeof(formRef) == "object" && formRef.tagName == "FORM")
	{
		form = formRef;
	}
	else if (typeof(formRef) == "string")
	{
		form = document.forms[formRef];
		if (form == null) form = document.getElementById(formRef);
	}
	if (form == null)
	{
		alert("No valid form could be found.")
		return;
	}
	else return form;
}

function UtilityParseInput(inputRef, formRef)
{
	var input = null;
	if (inputRef != null && typeof(inputRef) == "object" && ((inputRef.tagName == "INPUT" && (inputRef.type == "text" || inputRef.type == "password" || inputRef.type == "radio" || inputRef.type == "checkbox")) || inputRef.tagName == "TEXTAREA" || inputRef.tagName == "SELECT"))
	{
		input = inputRef;
	}
	else if (typeof(inputRef) == "string")
	{
		if (!formRef)
		{
			var foundInput = false;
			for (var i=0; i<document.forms.length; i++)
			{
				if (foundInput == false)
				{
					for (var j=0; j<document.forms[i].elements.length; j++)
					{
						if (document.forms[i].elements[j].name == inputRef)
						{
							input = document.forms[i].elements[j];
							foundInput = true;
							break;
						}
					}
				}
			}
			if (input == null) input = document.getElementById(inputRef);
			if (input == null) input = document.getElementById(inputPrefix + input);
		}
		else
		{
			var form = document.forms[formRef];
			if (form == null) form = document.getElementById(formRef);
			input = form.elements[inputRef];
			if (input == null) input = form.elements[inputPrefix + inputRef];
			if (input == null) input = document.getElementById(input);
			if (input == null) input = document.getElementById(inputPrefix + input);
		}
	}
	if (input == null)
	{
		alert("No valid form input could be found.")
		return;
	}
	return input;
}

function UtilityTrim(string)
{
	if (string == null) return "";
	while (string.charAt(0) == " " || string.charCodeAt(0) == 10 || string.charCodeAt(0) == 13 || string.charCodeAt(0) == 9)
	{
		string = string.substring(1, string.length);
	}
	while (string.charAt(string.length - 1) == " " || string.charCodeAt(string.length - 1) == 10 || string.charCodeAt(string.length - 1) == 13 || string.charCodeAt(string.length - 1) == 9)
	{
		string = string.substring(0, string.length - 1);
	}
	return string;
}