var alertMessage = "alertmessage";
var alertMessageText = "Please fill in the required values then re-submit.";
var alertCssClassName = "alert";
var defaultCssClassName = "default";

function validateForm(theForm, elementsList)
{
	var retVal = 0;
	// clear alert message...
	clearAlertMessage();
	// if the elementsList is null, check to see if there is an elementslist hidden field.
	// if elementsList is still null, the do a basic validation of, text, select, textarea, and password fields.
	if (elementsList == null) {
		if (theForm.elementsList == null) {
			for (var i=0; i<theForm.elements.length; i++) {
				if (theForm.elements[i].type != null) {
					if (theForm.elements[i].type == "text" || theForm.elements[i].type == "select-one" || theForm.elements[i].type == "textarea" || theForm.elements[i].type == "select-multiple" || theForm.elements[i].type == "password") {
						if (elementsList == null) 
							elementsList = theForm.elements[i].name;
						else
							elementsList += ";" + theForm.elements[i].name;
					}
				}
			}
		}
		else {
			elementsList = theForm.elementslist.value;
		}
	}

	var theElements = elementsList.split(";")
	for (var i=0; i<theElements.length; i++) {
		var x = theElements[i];
		if (theElements[i].indexOf(":") > -1) {
			if (!validateField(theForm.elements[theElements[i].substring(0, theElements[i].indexOf(":"))], theElements[i].substring(theElements[i].indexOf(":")+1, theElements[i].length)))
				retVal++;
		}
		else {
			if (!validateField(theForm.elements[theElements[i]]))
				retVal++;
		}
	}
	if (retVal != 0) {
		// set alert message...
		setAlertMessage();
	}
	return retVal == 0;
}

function validateField(theField, args, clearAlertMessageStatus)
{
	if (clearAlertMessageStatus == true)
		clearAlertMessage();
	
	var alertElement = "";
	if (theField.length != null && theField[0].type == "radio")
		alertElement = theField[0].name;
	else
		alertElement = theField.id;
	clearAlertStatus(alertElement);
	
	var retVal = 0;
	var theForm = theField.form;
	if (args != null && args != "") {
		var tmpArray = args.split(":");
		switch (tmpArray.length) {
			case 3:
				if (tmpArray[1] == "compare") {
					// 2nd parameter: required = 1, 3rd parameter specifies datatype, fourth is the field to compare against..
					if (!isValid(getValue(theField), "1", "compare", getValue(theForm.elements[tmpArray[2]])))
						retVal++;
				}
				else {
					// 2nd parameter: required = 1 or not required = 0, 3rd parameter specifies datatype, fourth is a custom regex string...
					if (!isValid(getValue(theField), tmpArray[0], tmpArray[1], tmpArray[2]))
						retVal++;
				}
				break;
			case 2:
				if (!isValid(getValue(theField), tmpArray[0], tmpArray[1]))
					retVal++;
				break;
			case 1:
				if (!isValid(getValue(theField), "1", tmpArray[0]))
					retVal++;
				break;
			default:
				if (isEmptyString(getValue(	theField)))
					retVal++;
		}
	}
	else {
		if (isEmptyString(getValue(	theField)))
			retVal++;
	}
	if (retVal != 0) {
		if (theField.length != null && theField[0].type == "radio")
			setAlertStatus(alertElement);
		else
			setAlertStatus(alertElement);
	}
	return retVal == 0;
}

// returns the value of the element depending on input element type...
function getValue(theElement) {
	var retVal = "";
	switch (theElement.type) {
		case "select-one":
			retVal = theElement.options[theElement.selectedIndex].value;
			break;
		case "select-multiple":
			for (var i=0; i<theElement.options.length; i++) {
				if (theElement.options[i].selected) {
					if (retVal != "") retVal += ",";
						retVal += theElement.options[i].value;
				}
			}
			break;
		case "text":
			retVal = theElement.value;
			break;
		case "hidden":
			retVal = theElement.value;
			break;
		case "password":
			retVal = theElement.value;
			break;
		case "textarea":
			retVal = theElement.value;
			break;
		default:
		if (theElement.length) { // radio???
			if (theElement[0].type == "radio") {
				for (var i=0; i<theElement.length; i++) {
					if (theElement[i].checked) {
						retVal = theElement[i].value;
						break;
					}
				}
			}
		}
	}
	return retVal;
}

function isValid(stringValue, required, dataType, arg4) {
	if (required == "0" && isEmptyString(stringValue)) {
		// it's not required, so empty is ok...
		return true;
	}
	else if (required == "1" && isEmptyString(stringValue)) {
		// it's required, so empty is NOT ok...
		return false;
	}
	else {
		// whether it's required or not, make sure the data is correct...
		switch (dataType) {
			case "maxlength":
				return stringValue.length <= parseInt(arg4);
				break;
			case "email":
				return isMatch(stringValue, /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/);
			case "emaillist":	// comma separated list of email addresses...
				var pattern = /[\s,]+/g;	// replace all whitespace and/or commas with delimiter '|'...
				var tmpEmailString = stringValue.replace(pattern,"|");
				pattern = /[\|]$/;			// replace delimiter '|' at end of line with nothing...
				tmpEmailString = tmpEmailString.replace(pattern,"");
				var tmpEmailArray = tmpEmailString.split("|");
				var err = 0;
				for (var i=0; i<tmpEmailArray.length; i++) {
					if (!isMatch(tmpEmailArray[i], /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/))
						err++;
				}
				return err == 0;
			case "date":
				switch (arg4) {
					case "mm-dd-yyyy":
						if (isMatch(stringValue, /^\d{1,2}-\d{1,2}-\d{4}$/)) {
							var tmpVal = stringValue.split("-");
							return isValidDate(tmpVal[0], tmpVal[1], tmpVal[2]);
						}
						else {
							return false;
						}
					case "yyyy-mm-dd":
						if (isMatch(stringValue, /^\d{4}-\d{1,2}-\d{1,2}$/)) {
							var tmpVal = stringValue.split("-");
							return isValidDate(tmpVal[1], tmpVal[2], tmpVal[0]);
						}
						else {
							return false;
						}
					default:	// mm/dd/yyyy
						if (isMatch(stringValue, /^\d{1,2}\/\d{1,2}\/\d{4}$/)) {
							var tmpVal = stringValue.split("/");
							return isValidDate(tmpVal[0], tmpVal[1], tmpVal[2]);
						}
						else {
							return false;
						}
				}
			case "phone":
				return isMatch(stringValue, /(((((^[(](\d{3})[)][ ]?)|(^\d{3})[- ]))(\d{3})[- ](\d{4}))|(\d{10})|(\d{3}\.\d{3}\.\d{4}))(.){0,13}$/);
			case "zip":
				return isMatch(stringValue, /^\d{5}(-\d{4})?$/);
			case "ssn":
				return isMatch(stringValue, /^\d{3}-\d{2}-\d{4}$|^\d{3}\d{2}\d{4}$/);
			case "numeric":
				return !isNaN(stringValue);
			case "integer":
				alert("TODO: function isValid(stringValue, integer);");
				return false;
				//return !isNaN(parseInt(stringValue)); -- doesn't work...
			case "float":
				alert("TODO: function isValid(stringValue, float);");
				return false;
				//return !isNaN(parseFloat(stringValue)); -- doesn't work...
			case "currency":
				alert("TODO: function isValid(stringValue, currency);");
				return false;
			case "compare":
				return stringValue == arg4;
			case "regexp":
				return isMatch(stringValue, arg4);
		}
	}
}
function isEmptyString(stringValue){
	var tmp = "";
	if (stringValue != "") {
		for (var i=0; i<stringValue.length; i++) {
			if (stringValue.charAt(i) != " ")
				tmp += stringValue.charAt(i);
		}
	}
	return tmp.length == 0;
}
function isMatch(stringValue, regexString) {
	var regex = new RegExp(regexString);
	var matches = regex.exec(stringValue);
	return (matches != null && stringValue == matches[0]);
}
function isValidEmail(stringValue) {
	if (isEmptyString(stringValue))
		return false;
	var regex = new RegExp(/^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/);
	var matches = regex.exec(stringValue);
	return (matches != null && stringValue == matches[0]);
}
function isValidDate(month, day, year) {
	if (!(parseInt(month, 10) > 0 && parseInt(month, 10) < 13))
		return false;
	else if (!(parseInt(day, 10) > 0 && parseInt(day, 10) < getDays(parseInt(month, 10), parseInt(year, 10))+1))
		return false;
	else if (!(parseInt(year, 10) > 1899 && parseInt(year, 10) < 2026))
		return false;
	else
		return true;
}
function getDays(m, y) {
	var daysInMonth = new Array(12);	// makeArray(12);
	daysInMonth[0] = 31;
	daysInMonth[1] = februaryDays(y);
	daysInMonth[2] = 31;
	daysInMonth[3] = 30;
	daysInMonth[4] = 31;
	daysInMonth[5] = 30;
	daysInMonth[6] = 31;
	daysInMonth[7] = 31;
	daysInMonth[8] = 30;
	daysInMonth[9] = 31;
	daysInMonth[10] = 30;
	daysInMonth[11] = 31;
	return daysInMonth[parseInt(m) -1];
}
function februaryDays(year) {   
	// February has 29 days in any year evenly divisible by four, EXCEPT for centurial years which are not also divisible by 400.
	return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
}
function setAlertStatus(elementId) {
	// find any element intended to be an alert notification by looking for the 'alert_' prefix + element id, otherwise use the element itself...
	if (document.getElementById("alert_" + elementId)) {
		document.getElementById("alert_" + elementId).className = alertCssClassName;
	}
	else {
		if (document.getElementById(elementId) != null)
			document.getElementById(elementId).className = alertCssClassName;
	}
}
function clearAlertStatus(elementId) {
	// clear the label or element...
	if (document.getElementById("alert_" + elementId) != null) {
		if (document.getElementById("alert_" + elementId).className == alertCssClassName)
			document.getElementById("alert_" + elementId).className = defaultCssClassName;
	}
	else if (document.getElementById(elementId) != null) {
		if (document.getElementById(elementId).className == alertCssClassName)
			document.getElementById(elementId).className = defaultCssClassName;
	}
}
function setAlertMessage() {
	// set alert message...
	if (document.getElementById(alertMessage) != null) {
		if (isEmptyString(document.getElementById(alertMessage).innerHTML)) {
			document.getElementById(alertMessage).innerHTML = alertMessageText;
		}
		document.getElementById(alertMessage).className = alertCssClassName;
		document.getElementById(alertMessage).style.display = "block";
	}
	else {
		alert(alertMessageText);
	}
}
function clearAlertMessage() {
	// clear alert message...
	if (document.getElementById(alertMessage) != null) {
		if (document.getElementById(alertMessage).style.display == "block")
			document.getElementById(alertMessage).style.display = "none";
	}
}
