/* !!NOTE!! this file has a dependence on commonFunctions.js */
var debug = false;

var minPhoneNumberLength = 5; //7 with area code, 5 without
var maxPhoneNumberLength = 10; //10 with area code, 7 without
var minUsernameLength = 3;
var minPasswordLength = 6;

var areaCodeHolder = "";
var passwordHolder = ""; //used to confirm passwords match
var emailAddressHolder = ""; //used to confirm email addresses match
var radioGroupHolder = new Array(); //used to prevent useless radio selection checking if one already selected

var invalidEntryCount = 0;
var formErrorText = ""; //defined below!
var extraErrorText = "";

var termsAccepted = true;

function validateForm(theForm, defaultValidation){
	var formFieldErrors = "";
	var readyToGo = true;
	var formElements = theForm.elements;
	var firstInvalidEntry = -1;
	var invalidEntryCount = 0;
	//Global variables
	radioGroupHolder = new Array();
	formErrorText = "Please correct the highlighted entries\n\n(Mouse over each entry to see the error)\n\n";
	extraErrorText = "";

	for (var i=0; i < formElements.length; i++) {
		var currentElement = formElements[i];
		var currentElementType = currentElement.getAttribute("type");
		var currentElementRequired = currentElement.getAttribute("required");

		var minRequiredLength = currentElement.getAttribute("minRequiredLength");
		var maxRequiredLength = currentElement.getAttribute("maxRequiredLength");
		var allowedExtensions = currentElement.getAttribute("allowedExtensions");
		
		if (currentElementType == "hidden" || currentElementType == "submit" || currentElementType == "reset" || currentElementType == "image"){
			validateField = false;
		} else if (currentElementRequired == "true"){
			validateField = true;
		} else if (currentElementRequired == "false" && (currentElementType == "text" || currentElementType == "file") && currentElement.value){
			//an unrequired field will still need to be checked for valid characters etc if it's not empty!
			validateField = true;
		} else if (currentElementRequired == "false"){
			validateField = false;
		} else if (defaultValidation == "all"){
			validateField = true;
		} else {
			validateField = false;
		}

		var isEmpty = !currentElement.value || currentElement.value == " ";
		//Don't bother validating submit, reset or hidden inputs.
		if (validateField){
			if (currentElementType == "checkbox" && checkboxSelected(currentElement) != true){
				applyHighlighting(currentElement, true);
				readyToGo = false;
				invalidEntryCount = invalidEntryCount + 1;
			} else if (currentElementType == "radio" && !tryIsInArray(currentElement.name, radioGroupHolder) && radioOptionSelected(currentElement) != true){
				applyHighlighting(currentElement, true);
				readyToGo = false;
				invalidEntryCount = invalidEntryCount + 1;
			} else if (isEmpty){
				tryToSetTooltip(currentElement, 'This entry is required');
				applyHighlighting(currentElement, true);
				readyToGo = false;
				invalidEntryCount = invalidEntryCount + 1;
				if (firstInvalidEntry < 0) firstInvalidEntry = i;
			} else if (isValid(currentElement, minRequiredLength, maxRequiredLength, allowedExtensions) != true){
				tryToSetTooltip(currentElement, isValid(currentElement, minRequiredLength, maxRequiredLength, allowedExtensions));
				applyHighlighting(currentElement, true);
				readyToGo = false;
				invalidEntryCount = invalidEntryCount + 1;
				if (firstInvalidEntry < 0) firstInvalidEntry = i;
			} else {
				tryToSetTooltip(currentElement, '');
				applyHighlighting(currentElement, false);
			}	
		} else {
			tryToSetTooltip(currentElement, '');
			applyHighlighting(currentElement, false);
		}
	}
		//ADD FORM-SPECIFIC CODE HERE (include form page url)  until this script can handle radio, checkboxes and selects
		//Ensure that readyToGo is set to false if there is a field error

//	if (!readyToGo) alert("Please correct the highlighted fields\n\n"+formFieldErrors);
	if (!readyToGo){
		if (invalidEntryCount == 1 && !termsAccepted){
			formErrorText = extraErrorText;
		} else {
			formErrorText = formErrorText + extraErrorText;
		}
		try{ //in the case of checkboxes, this could fail
			formElements[firstInvalidEntry].focus(); //be nice, jump to the first error
		} catch(e){
			debugError(e);
		}
		try{ //if a formMessages DIV hasn't been coded into the html, use an alert
			formMessageDiv = document.getElementById('formMessages');
			formMessageDiv.className = "errorText";
			formMessageDiv.innerHTML = formErrorText;
			tryToScrollToObject(formMessageDiv, 0, -12);
		} catch (e){
			alert(formErrorText);
		}
	}
	return readyToGo;
}


function checkboxSelected(currentElement){
	if ((currentElement.getAttribute("field") == "terms") && !currentElement.checked){
		extraErrorText = extraErrorText + "You must read through and agree to the \nTerms and Conditions before continuing.\n";
		termsAccepted = false;
		return false;
	} else {
		return currentElement.checked;
	}
}

function isValid(input, minLength, maxLength, allowedExtensions){
	var result;
	try{
		switch (input.getAttribute("field")){
			case 'name':
				result = isValidName(input, minLength, maxLength);
				break;
			case 'email':
				emailAddressHolder = input.value;
				result = isValidEmail(input);
				break;
			case 'confirmEmail':
				result = emailAddressesMatch(input);
				break;
			case 'accountNumber':
				result = isValidAccountNumber(input);
				break;
			case 'areaCode':
				areaCodeHolder = input.value;
				result = isValidAreaCode(input);
				break;
			case 'phoneNumber': //USE THIS!
				result = isValidPhoneNumber(input);
				break;
			case 'phone':
				result = isValidPhoneNumber(input);
				break;
			case 'username':
				result = isValidUsername(input, minLength, maxLength);
				break;
			case 'password':
				passwordHolder = input.value;
				result = isValidPassword(input, minLength, maxLength);
				break;
			case 'confirmPassword':
				result = passwordsMatch(input);
				break;
			case 'file':
				result = isValidExtension(input, allowedExtensions);
				break;
			case 'url':
				result = isValidURL(input);
				break;
			default :
				result = true;
		}
	} catch(e) {
		debugError(e, "isValid switch");
		result = true;
	}
	return result;
}


function isValidName(input, minLength, maxLength) {
	//put code here to check length, non-number etc
	var name = input.value;
	var minLength = 1;
	var maxLength = 250;

	if (name.length < 3){
		return "This entry is too short";
	} else {
		var errorText = "Keyword can only contain letters";
		//allow only a-z type characters (inc special characters eg in Polish form of Brzezinski) and spaces, apostrophes dashes, dots and commas
		//http://jrgraphix.net/research/unicode_blocks.php
		var nameRegex = /^([a-z\xC0-\xF6\.\s]+)$/gi;

		var re = new RegExp(nameRegex);
		if (name.match(re))
			return true;
		else
			return errorText;
	}
}


function isValidEmail(input) {
	var emailAddress = input.value;
	errorText = "This entry is invalid";

	//http://www.remote.org/jochen/mail/info/chars.html
	var emailRegex = "^([a-zA-Z0-9\-\._\+]+)@" + 
					"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))" + 
					"([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
		
	var re = new RegExp(emailRegex);
	if (emailAddress.match(re))
		return true;
	else
		return errorText;

}


function isValidAccountNumber(input) {
	var accountNumber = input.value;
	var errorText = "Account number must be 8 digits";
	
	var accountNumberRegex = /^\d{8}$/g;

	var re = new RegExp(accountNumberRegex);
	if (accountNumber.match(re))
		return true;
	else
		return errorText;
/*	if (accountNumber.length == 8 && allValidChars(accountNumber, "number") == true){
		return true;
	} else {
		return "Account number must be 8 digits";
	}
*/
}


function isValidAreaCode(input) {
	//update to reduce phonenumber length requirement
	if (input.options[input.selectedIndex].value != ""){
		minPhoneNumberLength = 5;
		maxPhoneNumberLength = 7;
		return true;
	} else {
		return "Please select";
	}

}


function isValidPhoneNumber(input) {
	//add something to handle an area code dropdown too!
	var number = input.value;
	var minLength = minPhoneNumberLength;
	var maxLength = maxPhoneNumberLength;
	errors = "";
	
	number = number.replace(/[\s]/g,"");
	number = number.replace(/\+/g,"00");
	
	if (number.length < minLength || number.length > maxLength){ //must be a certain length
		errors = errors + "must be between " + minLength + " and " + maxLength + " characters in length; ";
	} 
	if (allValidChars(number, "number") != true){
		errors = errors + allValidChars(number, "number");
	}
	if (number.indexOf('+00') == -1 || //can't start with +00
		number.indexOf('000') == -1){ //can't start with 000

	}

	if (!errors == ""){
		return "This entry " + errors;
	} else {
		input.value = number;
		return true;
	}
}


function isValidUsername(input, minLength, maxLength){
	var username = input.value;
	minUsernameLength = (minLength == "" || minLength == null) ? minUsernameLength : minLength;
	maxUsernameLength = (maxLength == "" || maxLength == null) ? maxUsernameLength : maxLength;
	if (username.length >= minUsernameLength && username.length <= maxUsernameLength){
		return true;
	} else {
		return "Username must be between " + minUsernameLength + " and " + maxUsernameLength + " characters";
	}
	
}


function isValidPassword(input, minLength, maxLength){
	minPasswordLength = (minLength == "" || minLength == null) ? minPasswordLength : maxLength;
	maxPasswordLength = (maxLength == "" || maxLength == null) ? maxPasswordLength : maxLength;
	var password = input.value;
	if (password.length >= minPasswordLength && password.length <= maxPasswordLength){
		passwordHolder = password;
		return true;
	} else {
		return "Password must be between " + minPasswordLength + " and " + maxPasswordLength + " characters";
	}
}


function termsRead(checkBox, termsIframeId){
	/* !!NOTE!! Access or Permission denied errors will arise when the IFRAME src  */
	/* differs from the page domain - eg. local pages will fail on server iframes! */
	var termsIframe = parent.document.getElementById(termsIframeId);
	var iframedocumentheight = termsIframe.contentWindow.document.body.scrollHeight;
	var iframetopofscroll = termsIframe.contentWindow.document.body.scrollTop;
	var iframeheight = getElementHeight(termsIframeId);

	if ((iframedocumentheight - iframeheight) > iframetopofscroll + 1){
		checkBox.checked = false;
		alert("You must read through the Terms and Conditions before you agree to them.");
	}
}


function passwordsMatch(input){
	confirmPassword = input.value;
	if (passwordHolder == confirmPassword){
		return true;
	} else {
		return "Password and confirm password do not match";
	}
}

function emailAddressesMatch(input){
	confirmEmailAddress = input.value;
	if (emailAddressHolder == confirmEmailAddress){
		return true;
	} else {
		return "E-mail address and confirm e-mail address do not match";
	}
}

function isValidExtension(input, allowedExtensions){
	var filenameAndPath = input.value;
	var extension;
	var errorText = "is an invalid file type (allowed: " + allowedExtensions + ")";

	try{
		extension = filenameAndPath.substring(filenameAndPath.lastIndexOf('.') + 1, filenameAndPath.length);
	} catch(e) {
		debugError(e);
		return errorText;
	}

	var allowed = new Array();
	if (allowedExtensions.indexOf(',') > -1){
		allowed = allowedExtensions.split(',');
	} else {
		allowed = allowedExtensions;
	}
	
	if (extension == allowed || tryIsInArray(extension, allowed)){
		return true;
	} else {
		return errorText;
	}
}

function isValidURL(input){
	var url = input.value;
	var errorText = "This entry is invalid";

	//http://regexlib.com/REDetails.aspx?regexp_id=1374
	var urlRegex = /^((https?):\/\/){1}(([\d\w]|%[a-fA-f\d]{2,2})+(([\d\w]|%[a-fA-f\d]{2,2})+)?)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/gi;
	/*	
	var urlRegex = "^(https?://){1}" + //must have http(s)://
				"(([0-9]{1,3}\.){3}[0-9]{1,3}" + // IP- 199.194.52.184
				"|" + // allows either IP or domain
				"([0-9a-z_!~*'()-]+\.)*" + // tertiary domain(s)- www.
				"([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\." + // second level domain
				"[a-z]{2,6})" + // first level domain- .com or .museum
				"(:[0-9]{1,5})?" + // port number- :80
				"((/?)|" + // a slash isn't required if there is no file name
				"(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
*/
	var re = new RegExp(urlRegex);
	if (url.match(re))
		return true;
	else
		return errorText;
}

function allValidChars(field, type) {
	var validchars;
	if (type == "email")
		validchars = "abcdefghijklmnopqrstuvwxyz0123456789@.-_+";
	else if (type == "number")
		validchars = "01234567890-+ "
	else if (type == "url")
		validchars = "abcdefghijklmnopqrstuvwxyz0123456789.-_+:/{}%";
	for (var i=0; i < field.length; i++) {
		var letter = field.charAt(i).toLowerCase();
		if (validchars.indexOf(letter) != -1)
			continue;
		return "contains invalid characters (allowed: " + validchars + "); ";
		break;
	}
	return true;
}


function radioOptionSelected(input){
	//add functionality to avoid continuing this check if an option is already selected!
	theForm = input.form;
	radioGroup = theForm.elements[input.name];
	
	// set var radioSelected to false
	var radioSelected = false;
	// Loop from zero to the one minus the number of radio button selections
	for (counter = 0; counter < radioGroup.length; counter++){
		// If a radio button has been selected it will return true
		if (radioGroup[counter].checked){
			radioGroupHolder[radioGroupHolder.length] = input.name;
			return true;
		}
	}

	if (!radioSelected){
		// If there were no selections made display an alert box
		radioSelected = "Please select one";
	}
	return radioSelected;
}


/* BEGIN calls to functions defined in commonFunctions.js */
function tryToSetTooltip(element, tip){
	try{
		setTooltip(element, tip);
	} catch(e){
		debugError(e, "tryToSetTooltip");
	}
}

function tryToScrollToObject(object, horizontalAdjustment, verticalAdjustment){
	try{
		scrollToObject(object, horizontalAdjustment, verticalAdjustment);
	} catch(e){
		debugError(e, "tryToScrollToObject");
	}
}

function tryIsInArray(needle, haystack){
	try{
		return isInArray(needle, haystack);
	} catch(e){
		debugError(e, "tryIsInArray");
		return false;
	}
}
/* END calls to functions in commonFunctions.js */

function debugError(error, helpText){
	if (debug) alert("DEBUG ERROR: " + error + "\n" + helpText);
}


function checkTextAreaLength(currentLength, maxLength) {
	if (currentLength > maxLength){
        alert("Text too long. Must be " + maxLength + " characters or less");
        return false;
    }
    return true;
}


function checkTextAreaLength(field, maxLength) {
    if (field.value.length > maxLength) {
        alert("Text too long. Must be " + maxLength + " characters or less");
        field.value = field.value.substring(0, maxLength);
    }
}