var errors;
var errorsTabbed;
var errorFields;

/**
* Validates a form
* If type is 'page', the div#errorMessage must exist in the document
* @param form				The form element to validate
* @param type optional string		The type of display ('page' or 'alert')
* @param highlight optional bool	Should error fields be highlighted ('yes' or 'no')
*/
function validateForm(form, type, highlight) {
	var i;

	if (type != 'alert') {
		type = 'page';
	}
	if (type == 'page' && document.getElementById('errorMessage') == null) {
		type = 'alert';
	}
	if (highlight != 'no') {
		highlight = true;
	} else {
		highlight = false;
	}

	errors = new Array();
	errorsTabbed = new Array();
	errorFields = new Array();
	for (i=0; i<form.length; i++) {
		if (highlight) {
			showError(form.elements[i], false);
		}
		validate(form.elements[i]);
	}
	if (errors.length > 0 || errorsTabbed.length > 0) {
		// Highlight Error Fields
		if (highlight) {
			for (i=0; i<errorFields.length; i++) {
				showError(errorFields[i], true);
			}
		}
		// Combine Error Messages from Fields with or without TabIndexes
		for (i in errors) {
			errorsTabbed[errorsTabbed.length] = errors[i];
		}
		// Display the Error Message
		if (type == 'page') {
			// Display in the errorMessage tag on the page
			errorHTML = '';
			for (i=0; i<errorsTabbed.length; i++) {
				if (errorsTabbed[i]) {
					errorHTML += errorsTabbed[i] + "<br>";
				}
			}
			errorHTML += '<br>';
			document.getElementById('errorMessage').innerHTML = errorHTML;
			// Addresses Safari Redrawing Error (when window is already scrolled to the top)
			if (!window.scrollX) {
				window.scroll(0, 10);
			}
			// Scroll to Top of the Page
			window.scroll(0, 0);
		} else {
			// Display in an alert box
			errorString = "";
			for (i=0; i<errorsTabbed.length; i++) {
				if (errorsTabbed[i]) {
					errorString += errorsTabbed[i] + "\n";
				}
			}
			alert(errorString);
		}
		return false;
	} else {
		return true;
	}
}

function showError(element, isError) {
   	label = document.getElementById(element.name + "_label");
	if (label) {
		labelClass = (isError) ? "error" : "";
		label.className = labelClass;
	}
}

function validate(element) {
	if (element.type == 'NodeList') {
		for (subElt in element) {
			validate(subElt);
		}
	} else if (element) {
		if (element.req && isEmpty(element)) {
			if (element.type == 'file') {
				addToErrors(element, 'Please upload a file for the "' + element.pname + '".');
			} else {
				addToErrors(element, 'Please enter a value for the "' + element.pname + '" field.');
			}
			errorFields[errorFields.length] = element;
		} else if (element.checkOne && !atLeastOneChecked(element)) {
			addToErrors(element, 'Please check at least one "' + element.pname + '".');
			errorFields[errorFields.length] = element;
		} else if (element.email && element.value && !matchEmail(element)) {
			addToErrors(element, 'Please verify that the value in the "' + element.pname + '" field is a valid email address.');
			errorFields[errorFields.length] = element;
		} else if (element.phone && element.value && !matchPhone(element)) {
			addToErrors(element, 'Please verify that the value in the "' + element.pname + '" field is a valid 10-digit phone number with an area code.');
			errorFields[errorFields.length] = element;
		} else if (element.url && element.value && !matchURL(element)) {
			addToErrors(element, 'Please verify that the value in the "' + element.pname + '" field is a valid url beginning with "http://".');
			errorFields[errorFields.length] = element;
		} else if (element.lessThan && element.selectedIndex > element.lessThan.selectedIndex) {
			addToErrors(element, 'The value of the "' + element.pname + '" field must be less than the value of the "' + element.lessThan.pname + '" field.');
			errorFields[errorFields.length] = element;
		} else if (element.reqIfVal && element.options[element.selectedIndex].value == element.reqIfVal && element.reqOther.value == "") {
			addToErrors(element, 'If you select "' + element.reqIfName + '" for "' + element.pname + '", please fill out the "' + element.reqOther.pname + '" field as well.');
			errorFields[errorFields.length] = element;
		} else if (element.reqIfChecked && element.checked && element.reqOther.value == "") {
			addToErrors(element, 'If you select "' + element.reqIfName + '" for "' + element.pname + '", please fill out the "' + element.reqOther.pname + '" field as well.');
			errorFields[errorFields.length] = element;
		} else if (element.min || element.max) {
			numWords = wordCount(element);
			if ((element.max && numWords > element.max) || (element.min && numWords < element.min)) {
				if (!element.max) {
					reqLen = 'at least ' + element.min;
				} else if (!element.min) {
					reqLen = 'no more than ' + element.max;
				} else {
					reqLen = 'between ' + element.min + ' and ' + element.max;
				}
				addToErrors(element, 'The ' + element.pname + ' field must be ' + reqLen + ' words long.  It currently contains ' + numWords + ' words.');
				errorFields[errorFields.length] = element;
			}
		}
	}
}

function addToErrors(element, message) {
	if (errors.length == 0 && errorsTabbed.length == 0 && element.tabIndex) {
		tabbedFieldsFirst = true;
	}
	if (element.tabIndex && element.tabIndex >= 0) {
		errorsTabbed[element.tabIndex] = message;
	} else {
		errors[errors.length] = message;
	}
}

function atLeastOneChecked(element) {
	form = element.form;
	for (i=0; i<form.elements.length; i++) {
		if (form.elements[i].name == element.name && form.elements[i].checked) {
			return true;
		}	
	}
	return false;
}

function atLeastOneSelected(element) {
	for (i=0; i<element.options.length; i++) {
		if (element.options[i].selected) {
			return true;
		}	
	}
	return false;
}

function matchEmail(element) {
	// Matches an Email or a URL
	email = element.value.match(/^([_A-Za-z0-9-]+)(\.[_A-Za-z0-9-]+)*@([A-Za-z0-9-]+)(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,4})$/);
	url = element.value.match(/^http(s)?\:\/\/.+$/);
	return (email || url);
}

function matchPhone(element) {
	return element.value.match(/^\(?\d\d\d\)?(\.|-|\s*)?(\d\d\d)(\s*|\.|-)?\d\d\d\d$/);
}

function matchURL(element) {
	return element.value.match(/^http(s)?:\/\/.+\..+$/);
}

function isEmpty(element) {
	if (element.type == 'text' || element.type == 'textarea' || element.type == 'hidden' || element.type == 'password' || element.type == 'file') {
		if (element.value == "") {
			return true;
		}
	} else if (element.type == 'select-one') {
		if (element.options[element.selectedIndex].value == "") {
			return true;
		}
	} else if (element.type == 'select-multiple') {
		return !atLeastOneSelected(element);
	} else if (element.type == 'radio') {
		return !atLeastOneChecked(element);
	} else {
		alert('The type of form element "' + element.name + '" (' + element.type + ') has not been accounted for yet in formValidation.js.  Please update the code.');
		return false;
	}
}

function checkCountry(country, state) {
	star = document.getElementById("stateStar");
	if (country[country.selectedIndex].value != 'US') {
		// Country is US
		star.className = "hideMe";
		state.req = false;
		showError(state, false);
		state.disabled = "disabled";
	} else {
		// Country is not US
		star.className = "displayMe";
		state.req = true;
		state.disabled = false;
	}

	/*
	if (!state.disabled && state[state.selectedIndex].value == 'Outside the US') {
		for (var i=0; i < country.options.length; ++i) {
			if (country.options[i].value = '') {
				country.options[i].selected = true;
			}
		}
		country.selectedIndex = 0;
	}
	*/
}

function checkLength(textarea, maxChars, countSpan) {
	if (textarea.value.length > maxChars) {
   	    textarea.value = textarea.value.substring(0, textarea.value.length - (textarea.value.length - maxChars));
	}
	if (countSpan) {
		document.getElementById(countSpan).innerHTML = "Characters remaining: " + (maxChars - textarea.value.length);
	}
}

function wordCount(element) {
	textVal = element.value;
	if (textVal) {
		textVal = textVal.replace(/<br \/>/gi, ' ');
		textVal = textVal.replace(/<br>/g, ' ');
		textVal = textVal.replace(/<p>/g, ' ');
		textVal = textVal.replace(/<\/p>/g, ' ');
		textVal = textVal.replace(/&nbsp;/g, ' ');
		textVal = textVal.replace(/<.+?>/g, '');
		if (textVal) {
			match = textVal.match(/\S+/g);
			if (match) {
				if (match.length) {
					return match.length;
				}
			}
		}
	}
	return 0;
}

function checkWordCount(textarea, maxWords, countSpan, autodelete) {
	textVal = textarea.value;
	textVal = textVal.replace(/<br \/>/gi, ' ');
	textVal = textVal.replace(/<br>/g, ' ');
	textVal = textVal.replace(/<p>/g, ' ');
	textVal = textVal.replace(/<\/p>/g, ' ');
	textVal = textVal.replace(/&nbsp;/g, ' ');
	textVal = textVal.replace(/<.+?>/g, '');
	searchRE = new RegExp("\\s*(\\S+\\s*){0," + maxWords + "}");
	if (textVal) {
		numWords = textVal.match(/\S+/g).length;
	} else {
		numWords = 0;
	}
	if (autodelete && numWords > maxWords) {
   	    textarea.value = textarea.match(searchRE)[0];
	}
	if (countSpan) {
		wordsLeft = (maxWords - numWords);
/**
		if (wordsLeft < 0) {
			wordsLeft = 0;
		}
*/
		document.getElementById(countSpan).innerHTML = "Words remaining: " + wordsLeft;
	}
}