function FormManager(form,submitDisable) {
	this.form = form;
	this.submitDisable = submitDisable;
	this.validations = new Array();
	this.exceptions = new Array();
	this.setup();
}

FormManager.prototype.setup = function () {
	this.alerts = new Array();
	this.focusField = '';
};

FormManager.prototype.checkForm = function () {
	if (this.submitDisable) {
		this.buttonsDisabled(true);
	}
	if (document.getElementById(this.form.name+'SubmitValue')) {
		if (document.getElementById(this.form.name+'SubmitValue').value == 'Cancel') {
			return true;
		}
	}
	var i;
	// first reset classes to defaults
	for (i=0; i<this.validations.length; i++) {
		this.resetClass($(this.validations[i].field));
	}
	// then validate
	for (i=0; i<this.validations.length; i++) {
		if (!this.isException(this.validations[i].field)) {
			this.validate(this.validations[i]);
		}
	}
	if (this.alerts.length > 0) {
		if ($(this.form.name+'SubmitValue')) {
			$(this.form.name+'SubmitValue').value = '';
		}
		if (this.submitDisable) {
			this.buttonsDisabled(false);
		}
		alert(this.alerts.join("\n"));
		$(this.focusField).focus();
		this.setup();
		return false;
	}
	return true;
};

FormManager.prototype.addAlert = function (field,msg) {
	this.alerts.push(msg);
	if (this.focusField == '') {
		this.focusField = field;
	}
};

FormManager.prototype.addValidation = function (types,field,display) {
	var validation = new FormValidation(types,field,display);
	this.validations.push(validation);
};

FormManager.prototype.addException = function (affectedFields,testFields,testValues) {
	var exception = new FormException(affectedFields,testFields,testValues);
	this.exceptions.push(exception);
};

FormManager.prototype.resetClass = function (field) {
	if (field.defaultClass) {
		field.className = field.defaultClass;
	} else {
		field.className = '';
	}
};

FormManager.prototype.isException = function (field) {
	// loop through the exceptions
	var i;
	for (i=0; i<this.exceptions.length; i++) {
		// if the field in question exists in the affectedFields of one of the exceptions, examine further
		if (this.exceptions[i].affectedFields.toString().indexOf(field) != -1) {
			// loop through the exception textFields to determine eligibility for an exception
			var k;
			for (k=0; k<this.exceptions[i].testFields.length; k++) {
				// the testField must exist
				if ($(this.exceptions[i].testFields[k])) {
					// if the testField value doesn't match the testValue, return false
					if ($(this.exceptions[i].testFields[k]).value != this.exceptions[i].testValues[k]) {
						return false;
					}
				} else {
					// the testField doesn't exist, return false
					return false;
				}
			}
			// this field passes the tests for an exception, so we do not need to validate it, return true
			return true;
		}
	}
	return false;
};

FormManager.prototype.validate = function (validation) {
	var i;
	for (i=0; i<validation.validations.length; i++) {
		this['validate'+validation.validations[i]](validation.field,validation.display);
	}
};

FormManager.prototype.setFieldError = function (field) {
	field.defaultClass = field.className;
	field.className = 'formError';
}

FormManager.prototype.validateNonempty = function (field,display) {
	var fieldElement = $(field);
	if (fieldElement.disabled == false) {
		if (fieldElement.value == '') {
			this.setFieldError(fieldElement);
			this.addAlert(fieldElement.name,display + ' cannot be empty.');
			return false;
		}
	}
	return true;
};

FormManager.prototype.validateNumeric = function (field,display) {
	var field = $(field);
	if (field.disabled == false) {
		if (field.value != '') {
			var pattern = /^\-?\d*\.?\d*$/;
			if (!field.value.match(pattern)) {
				field.value = '';
				this.setFieldError(field);
				this.addAlert(field.name,display + ' must be numeric.');
				return false;
			}
		}
	}
	return true;
};

FormManager.prototype.validateInteger = function (field,display) {
	var field = $(field);
	if (field.disabled == false) {
		var pattern = /^\d*$/;
		if (!field.value.match(pattern)) {
			field.value = '';
			this.setFieldError(field);
			this.addAlert(field.name,display + ' may only contain numbers.');
			return false;
		}
	}
	return true;
};

FormManager.prototype.validateAlphanumeric = function (field,display) {
	var field = $(field);
	if (field.disabled == false) {
		var pattern = /^[\d\w]*$/;
		if (!field.value.match(pattern)) {
			field.value = '';
			this.setFieldError(field);
			this.addAlert(field.name,display + ' may only contain letters and numbers.');
			return false;
		}
	}
	return true;
};

FormManager.prototype.validateEmail = function (field,display) {
	var field = $(field);
	if (field.disabled == false) {
		if (field.value != '') {
			var pattern = /^[a-zA-Z0-9\._-]+@[a-zA-Z0-9][a-zA-Z0-9-]*(\.[a-zA-Z0-9_-]+)*\.([a-zA-Z]{2,6})$/;
			if (!field.value.match(pattern)) {
				field.value = '';
				this.setFieldError(field);
				this.addAlert(field.name,display + ' must be a valid email address.');
				return false;
			}
		}
	}
	return true;
};

FormManager.prototype.validateMMDDYY = function (field,display) {
	var field = $(field);
	if (field.disabled == false) {
		if (field.value != '') {
			if (obj.value.match(/^(\d{2})(\d{2})(\d{2})$/)) {
				var d = new Date();
				var yyyy = d.getFullYear() - (d.getFullYear() % 100) + parseInt(RegExp.$3, 10);
				var dd = parseInt(RegExp.$2, 10);
				var mm = parseInt(RegExp.$1, 10) - 1;
				if ( mm < 0 || mm > 11 ) {
					this.addAlert(field.name,display + ' has an invalid month value. Valid months values are 01 to 12.');
					this.setFieldError(field);
					return false;
				}
				
				// get last day in month
				var d = (11 == mm) ? new Date(yyyy + 1, 0, 0) : new Date(yyyy, mm + 1, 0);
				
				// if date out of range
				if (dd < 1 || dd > d.getDate()) {
					var monthNames = "January February March April May June July August September October November December".split(" ");
					this.addAlert(field.name,display + ' has an invalid date value. Valid date values for ' + monthNames[mm] + ' are 01 to '+d.getDate().toString()+'.');
					this.setFieldError(field);
					return false;
				}
				
				return true;
			}
			this.addAlert(field.name,display + ' must have the format MMDDYY');
			this.setFieldError(field);
			return false;
		}
	}
	return true;
};

FormManager.prototype.buttonsDisabled = function (state) {
	for (i=0; i<this.form.elements.length; i++) {
		var tempobj = this.form.elements[i];
		if (tempobj.type) {
			var lcType = tempobj.type.toLowerCase();
			if (lcType == "submit" || lcType == "reset" || lcType == "button") {
				tempobj.disabled = state;
			}
		}
	}
};

function FormValidation(validations,field,display) {
	this.validations = validations.split(',');
	this.field = field;
	this.display = display;
}

function FormException(affectedFields,testFields,testValues) {
	this.affectedFields = affectedFields.split(',');
	this.testFields = testFields.split(',');
	this.testValues = testValues.split(',');
}
