/**
 * construction function for base ValidationTest class
 * @param {String} error message
 */
function ValidationTest(errorMessage) {
	this.errorMessage = errorMessage;
}

/**
 * @var {String} errorMessage property
 * @scope public
 */
ValidationTest.prototype.errorMessage = '';

/**
 * should be overridden to provide custom validation functionality
 * @return {Boolean} whether validation passed or not
 */
ValidationTest.prototype.isValid = function() {
	return true;
}

/*
 * LettersOnlyValidationTest class
 */

/**
 * construction function for LettersOnlyValidationTest
 * @param {String} error message
 */
function LettersOnlyValidationTest(errorMessage) {
	this.base = ValidationTest;
	this.base(errorMessage);
}

LettersOnlyValidationTest.prototype = new ValidationTest();

LettersOnlyValidationTest.prototype.isValid = function(testElement) {
	var text = testElement.value;
	var pattern = /^[a-zA-Z\s]*$/;
	return (pattern.test(text));
}

/**
 * EmailValidationTest class
 */

/**
 * construction function for EmailValidationTest
 * @param {String} error message
 */
function EmailValidationTest(errorMessage) {
	this.base = ValidationTest;
	this.base(errorMessage);
}

EmailValidationTest.prototype = new EmailValidationTest();

EmailValidationTest.prototype.isValid = function(testElement) {
	var text = testElement.value;
	//var pattern = /^[0-9a-z~!#$%&_-]([.]?[0-9a-z~!#$%&_-])*@[0-9a-z~!#$%&_-]([.]?0-9a-z~!#$%&_-])*$/;
	var pattern = /^.+@.+[.].+$/; // must have {something}@{something}.{something}
	return (pattern.test(text));
}

/*
 * NumbersOnlyValidationTest class
 */

/**
 * construction function for NumbersOnlyValidationTest
 * @param {String} error message
 */
function NumbersOnlyValidationTest(errorMessage) {
	this.base = ValidationTest;
	this.base(errorMessage);
}

NumbersOnlyValidationTest.prototype = new ValidationTest();

NumbersOnlyValidationTest.prototype.isValid = function(testElement) {
	var text = testElement.value;
	var pattern = /^[0-9]*$/;
	return (pattern.test(text));
}

/*
 * CompareFieldsValidationTest class
 */

/**
 * construction function for CompareFieldsValidationTest
 * @param {String} error message
 * @param {String} id of element to compare with
 */
function CompareFieldsValidationTest(errorMessage, compareWithElementId) {
	this.base = ValidationTest;
	this.base(errorMessage);
	this._compareWithElement = document.getElementById(compareWithElementId);
}

CompareFieldsValidationTest.prototype = new ValidationTest();

/**
 * @var {Object}
 * @scope private
 */
CompareFieldsValidationTest.prototype._compareWithElement = null;

CompareFieldsValidationTest.prototype.isValid = function(testElement) {
	var ok = (testElement.value == this._compareWithElement.value);
	if (this._compareWithElement.value == '') ok = true; // presume they've not had chance to enter a value yet.
	return ok;
}

/*
 * RequiredFieldsValidationTest class
 */

/**
 * construction function for ValidationTest
 * @param {String} error message
 */
function RequiredFieldsValidationTest(errorMessage) {
	this.base = ValidationTest;
	this.base(errorMessage);
}

RequiredFieldsValidationTest.prototype = new ValidationTest();

RequiredFieldsValidationTest.prototype.isValid = function(testElement) {
	var text = testElement.value;
	var pattern = /^\s*$/;
	return (!pattern.test(text));
}

/*
 * ConditionalValidationTest
 */

/**
 * construction function for ConditionalValidationTest - this wraps around another
 * validation test and calls a provided function to see whether to test the given
 * validation test
 *
 * @param {Function} condition function: is passed the element being tested, and should return
 *  true if the validation test is to go ahead, false otherwise
 * @param {Object} a ValidationTest derived object
 */
function ConditionalValidationTest(conditionFunction, validationTest) {
	this.base = ValidationTest;
	this.base(validationTest.errorMessage);
	this._validationTest = validationTest;
	this._conditionTest = conditionFunction;
}

ConditionalValidationTest.prototype = new ValidationTest();

ConditionalValidationTest.prototype.isValid = function(testElement) {
	if (this._conditionTest(testElement) === true) {
		return this._validationTest.isValid(testElement);
	} else {
		return true;
	}
}
