/******************************************************************************************************************************************************************
The following functions should be used throughout the application when validating User Name and Password fields
******************************************************************************************************************************************************************/

/*********************************************************************************
Constants which should reflect SOW14 Business Rules
*********************************************************************************/
var LOWER_CASE_CHARS = /[a-z]/;
var UPPER_CASE_CHARS = /[A-Z]/;
var MIXED_CASE_CHARS = /[A-Za-z]/;
var NUMERIC_CHARS = /[0-9]/;
var AMICA_NUMBER_FORMAT = /^[Nn]\d{3,9}$/;

//password related
var PASSWORD_MIN_LENGTH = 7;
var PASSWORD_MAX_LENGTH = 14;

//username related
var USERNAME_MIN_LENGTH = 6;
var USERNAME_MAX_LENGTH = 16;
var USERNAME_INVALID_CHARS = /[\'\"\[\]\;\/ \\=,+<>()*&!{}]/;
// '"[];/space\=,+<>()*&!{}

//security question & answers related
var QUESTION_AND_ANSWER_INVALID_CHARS = /[\/\\<>(){}\;]/;
// /\<>(){};

/*********************************************************************************
Function...:	ssoValidatePasswordWithName
Description: 	Used to validate the User, First and Last Name fields at password change 
returns....: 	returns an error message
*********************************************************************************/
function ssoValidatePasswordWithName(password, firstname, lastname) {
	var ssoErrMsg = "";
	
	//check if password contains the firstname
	if (containsChars(password, firstname, false)) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords cannot contain your First Name.<br/>";
	}
	
	//check if password contains the lastname
	if (containsChars(password, lastname, false)) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords cannot contain your Last Name.<br/>";
	}
	
	return ssoErrMsg;
}

/*********************************************************************************
Function...:	ssoValidateLoginFields
Description: 	Used to validate the User Name and Password fields at login attempt
returns....: 	returns an error message
*********************************************************************************/
function ssoValidateLoginFields(username) {
	var ssoErrMsg = "";
	
	//check User Name
	ssoErrMsg += ssoValidateLoginUsernameValue(username);
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} /* end ssoValidateLoginFields */

/*********************************************************************************
Function...:	ssoValidateUpdatePasswordFields
Description: 	used to validate the password values associated with an
				"Update Password" event.  These fields include "current", "new", and "confirm" passwords.
returns....: 	returns an error message
*********************************************************************************/
function ssoValidateUpdatePasswordFields(currentPassword, newPassword, confirmPassword, username) {
	var ssoErrMsg = "";
	
	if (currentPassword == "") {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Current Password is missing.<br/>";
	}
	
	//check newPassword and confirmPassword
	ssoErrMsg += ssoValidateNewPasswordFields(newPassword, confirmPassword, username);
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} /* end ssoValidateUpdatePasswordFields */

/*********************************************************************************
Function...:	ssoValidateNewPasswordFields
Description: 	used to validate the password values associated with an
				"Create New Password" event.  These fields include "new" and "confirm" passwords.
				This is also called from the ssoValidateUpdatePasswordFields function
returns....: 	returns an error message
*********************************************************************************/
function ssoValidateNewPasswordFields(newPassword, confirmPassword, username) {
	var ssoErrMsg = "";
	
	if ((confirmPassword == "") || (newPassword == "")) {
		if (newPassword == "") {
			ssoErrMsg += "<img src='/images/error_dot.gif'>New Password is missing.<br/>";
		}
		
		if (confirmPassword == "") {
			ssoErrMsg += "<img src='/images/error_dot.gif'>\"Re-enter Password\" is missing.<br/>";
		}
	} else {
		//check to see if the New Password is the same as Confirm Password
		if (confirmPassword != newPassword) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>New Password and Confirm Password do not match.<br/>";
		} else {
			//we know that new password and confirm password are equal
			//so proceed with the business rule validations for the new password
			ssoErrMsg += ssoValidateNewPasswordValue(newPassword, username);
		}
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
}

/****************************************************************************************
Function...: ssoValidateNewUsernameValue
Description: validates a NEW username value against SOW14 business rules
			new username values cannot have an Amica Number format
returns....: returns an error message
****************************************************************************************/
function ssoValidateNewUsernameValue(username) {
	var ssoErrMsg = "";
	
	if (username == "") {
		ssoErrMsg += "<img src='/images/error_dot.gif'>User Name is missing.<br/>";
	} else {
		/****************************************************************************************
		These rules are defined in the SOW14 SRS document
		****************************************************************************************/
		//check for invalid characters
		if (containsChars(username, USERNAME_INVALID_CHARS, true)) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>User Name cannot contain spaces or any of the following characters: \'\"[];/\\=,+<>()*&!{}<br/>";
		}
		
		//new usernames cannot be in the amica number format
		if (containsChars(username, AMICA_NUMBER_FORMAT, true)) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>User Name cannot be an Amica Number.<br/>";
		}
		
		//check for min and max length
		if ((username.length < USERNAME_MIN_LENGTH) || (username.length > USERNAME_MAX_LENGTH)) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>User Name must contain " + USERNAME_MIN_LENGTH + " to " + USERNAME_MAX_LENGTH + " characters.<br/>";
		}
		
		//username must not begin with a number
		if (containsChars(username.charAt(0), NUMERIC_CHARS, true)) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>User Name cannot begin with a numeric character.<br/>";
		}
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} //end ssoValidateNewUsernameValue

/****************************************************************************************
Function...: ssoValidateLoginUsernameValue
Description: a user that has not been provisioned yet will use Amica or Policy number as username
returns....: returns an error message
****************************************************************************************/
function ssoValidateLoginUsernameValue(username) {
	var ssoErrMsg = "";
	
	if (username == "") {
		ssoErrMsg += "Please enter your user name.<br/>";
	} else {
		/****************************************************************************************
		These rules are defined in the SOW14 SRS document
		****************************************************************************************/
		//check for invalid characters
		if (containsChars(username, USERNAME_INVALID_CHARS, true)) {
			ssoErrMsg += "<img src='/images/error_dot.gif'>User Name cannot contain spaces or any of the following characters: \'\"[];/\=,+<>()*&!{}<br/>";
		}
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} //end ssoValidateLoginUsernameValue

/****************************************************************************************
Function...: ssoValidateNewPasswordValue
Description: validates the new password value against SOW14 business rules
returns....: returns an error message
****************************************************************************************/
function ssoValidateNewPasswordValue(password, username) {
	var ssoErrMsg = "";
	
	/****************************************************************************************
	These rules are defined in the SOW14 SRS document
	****************************************************************************************/
	//check for min and max length
	if ((password.length < PASSWORD_MIN_LENGTH) || (password.length > PASSWORD_MAX_LENGTH)) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords must contain " + PASSWORD_MIN_LENGTH + " to " + PASSWORD_MAX_LENGTH + " characters.<br/>"
	}
	
	//as part of defect 8736, checking for upper and lower case will no longer be needed
	//check if password has at least 1 upper case letter
	//if (!containsChars(password,UPPER_CASE_CHARS, true))
	//ssoErrMsg += "Passwords must contain at least one upper case character<br/>";
	
	//check if password has at least 1 lower case letter
	//if (!containsChars(password,LOWER_CASE_CHARS, true))
	//ssoErrMsg += "Passwords must contain at least one lower case character<br/>";
	
	//check if password has at least 1 numeric value
	if (!containsChars(password, NUMERIC_CHARS, true)) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords must contain at least one numeric character.<br/>";
	}
	
	var passwordTrim = ssoTrim(password);
	if (passwordTrim.length < password.length) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords cannot begin or end with a space.<br/>";
	}
	
	//check if password contains the username
	if (containsChars(password, username, false)) {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Passwords cannot contain your User Name.<br/>";
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} //end ssoValidateNewPasswordValue

/****************************************************************************************
Function...: ssoValidateLoginPasswordValue
Description: a user that has not been provisioned may have a password that does not
			conform to the SOW14 business rules
returns....: returns an error message
****************************************************************************************/
function ssoValidateLoginPasswordValue(password) {
	var ssoErrMsg = "";
	
	if (password == "") {
		ssoErrMsg += "<img src='/images/error_dot.gif'>Password is missing.<br/>";
	}
	
	//currently there are no restrictions on the password value used to login
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoErrMsg;
} //end ssoValidateLoginUsernameValue

/****************************************************************************************
Function...: containsChars
Description: determines if input string contains at least 1 instance of any of the chars in charList
returns....: true (if it contains one or more) or false (if contains none)
****************************************************************************************/
function containsChars(stringValue, regExpValue, isCaseSensitive) {
	var oRegExp;
	if (isCaseSensitive) {
		oRegExp = new RegExp(regExpValue);
	} else {
		oRegExp = new RegExp(regExpValue, "i");
	}
	
	if (oRegExp.test(stringValue)) {
		return true;
	}
	return false;
}

/****************************************************************************************
Function...: ssoTrim
Description: trims leading and trailing spaces
returns....: Trimmed string value
****************************************************************************************/
function ssoTrim(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g, "");
}

/****************************************************************************************
Function...: ssoLTrim
Description: trims leading spaces
returns....: Left trimmed string value
****************************************************************************************/
function ssoLTrim(stringToTrim) {
	return stringToTrim.replace(/^\s+/, "");
}

/****************************************************************************************
Function...: ssoRTrim
Description: trims trailing spaces
returns....: Right trimmed string value
****************************************************************************************/
function ssoRTrim(stringToTrim) {
	return stringToTrim.replace(/\s+$/, "");
}

/******************************************************************************************************************************************************************
The following functions should be used throughout the application when validating Security Question and Answer fields.
******************************************************************************************************************************************************************/

/*********************************************************************************
Global Variables:	BASE_STANDARD_QUESTION_ELEMENT_ID
					BASE_CUSTOM_QUESTION_ELEMENT_ID
					BASE_ANSWER_ELEMENT_ID
					SOURCE_STANDARD_QUESTIONS_ELEMENT_ID
					NUMBER_OF_SECURITY_QUESTIONS

Description: 		BASE_STANDARD_QUESTION_ELEMENT_ID - This is the base id used for all Standard
					Question SelectList elements.
					i.e. BASE_STANDARD_QUESTION_ELEMENT_ID = "question" and the implementation
					on the page would result in the elements being named something
					like "question1", "question2", "question3"

					BASE_CUSTOM_QUESTION_ELEMENT_ID - This is the base id used for all Custom
					Security Question text fields.
					i.e. BASE_CUSTOM_QUESTION_ELEMENT_ID = "customquestion" and the implementation
					on the page would result in the elements being named something
					like "customquestion1", "customquestion2", "customquestion3"

					BASE_ANSWER_ELEMENT_ID - This is the base id used for all Security Answer text fields.
					i.e. BASE_ANSWER_ELEMENT_ID = "answer" and the implementation
					on the page would result in the elements being named something
					like "answer1", "answer2", "answer3"

					SOURCE_STANDARD_QUESTIONS_ELEMENT_ID - This is the element id of the invisible "control"
					SelectList for the Security Questions which has all the available
					questions.  It is used for rebuilding the individual Security Question
					SelectLists during the dynamic content handling.

					NUMBER_OF_SECURITY_QUESTIONS - This denotes the number of Security Questions

					CUSTOM_QUESTION - This is the value of the "Make up your own security question" option.

Note:				Pages looking to implement these functions will need to
					name the associated form elements to be consistent with these constants

Type....:	 		Various
*********************************************************************************/
var BASE_STANDARD_QUESTION_ELEMENT_ID = "question";
var BASE_CUSTOM_QUESTION_ELEMENT_ID = "customquestion";
var BASE_ANSWER_ELEMENT_ID = "answer";
var SOURCE_STANDARD_QUESTIONS_ELEMENT_ID = "allOptions";
var NUMBER_OF_SECURITY_QUESTIONS = 3;
var CUSTOM_QUESTION = "custom";

/*********************************************************************************
Function...:	validateAllQuestionAnswerElements
Description: 	This function aggregates the functions that validate
				Standard Questions,	Custom Questions, and Security Answers
returns....: 	returns an error message
*********************************************************************************/
function validateAllQuestionAnswerElements() {
	var ssoBlankValuesMsg = "";
	var ssoCustomQuestionMsg = "";
	var ssoAnswerMsg = "";
	var counter = 1;
	
	var standardQuestionValue = "";
	var standardQuestionValue = "";
	var customQuestionValue = "";
	var answerValue = "";
	
	//loop through the standard questions
	for (counter = 1; counter <= NUMBER_OF_SECURITY_QUESTIONS; counter++) {
		standardQuestionValue = document.getElementById(BASE_STANDARD_QUESTION_ELEMENT_ID + counter).value;
		if (ssoTrim(standardQuestionValue) == "") {
			ssoBlankValuesMsg = "<img src='/images/error_dot.gif'>Please make sure you have selected and answered all three security questions.<br/>";
			break;
		}
	}
	
	//loop through the custom questions
	for (counter = 1; counter <= NUMBER_OF_SECURITY_QUESTIONS; counter++) {
		standardQuestionValue = document.getElementById(BASE_STANDARD_QUESTION_ELEMENT_ID + counter).value;
		customQuestionValue = document.getElementById(BASE_CUSTOM_QUESTION_ELEMENT_ID + counter).value;
		//only check the value of the Custom Question IF the user elected to create their own question
		if (ssoTrim(standardQuestionValue) == CUSTOM_QUESTION) {
			if ((ssoBlankValuesMsg == "") && (ssoTrim(customQuestionValue) == "")) {
				ssoBlankValuesMsg = "<img src='/images/error_dot.gif'>Please make sure you have selected and answered all three security questions.<br/>";
			}
			
			if ((ssoCustomQuestionMsg == "") && containsChars(customQuestionValue, QUESTION_AND_ANSWER_INVALID_CHARS, true)) {
				ssoCustomQuestionMsg = "<img src='/images/error_dot.gif'>If you choose to create your own security question, please make sure the question and response do not include any of the following characters: /\\\<>(){};<br/>";
			}
		}
	}
	
	//loop through the answers
	for (counter = 1; counter <= NUMBER_OF_SECURITY_QUESTIONS; counter++) {
		answerValue = document.getElementById(BASE_ANSWER_ELEMENT_ID + counter).value;
		if ((ssoBlankValuesMsg == "") && (ssoTrim(answerValue) == "")) {
			ssoBlankValuesMsg = "<img src='/images/error_dot.gif'>Please make sure you have selected and answered all three security questions.<br/>";
		}
		
		if ((ssoAnswerMsg == "") && containsChars(answerValue, QUESTION_AND_ANSWER_INVALID_CHARS, true)) {
			ssoAnswerMsg = "<img src='/images/error_dot.gif'>The answer to your security question cannot contain any of the following characters: /\\\<>(){};<br/>";
		}
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return ssoBlankValuesMsg + ssoCustomQuestionMsg + ssoAnswerMsg;
}

/*********************************************************************************
Function...:	handleSelection
Description: 	Handles the event of making a selection in one of the Security
				Question SelectLists to dynamically add/remove options from the
				other SelectLists and not the one which the user just made a
				selection from
returns....: 	void
*********************************************************************************/
function handleSelection(selectListId, customQuestionDivId) {
	//get an array of the options that are already selected by the other SelectLists
	var arrayOfSelectedValues = getAllSelectedValues();
	
	//create an array with the element ids of the Security Question SelectLists
	var arrayOfQuestionElementIds = getArrayOfElementIds(BASE_STANDARD_QUESTION_ELEMENT_ID, NUMBER_OF_SECURITY_QUESTIONS);
	
	//show or hide the Custom Question <div> depending on if the user selected or deselected the "Make up your own question..." option
	handleCustomQuestionField(selectListId, customQuestionDivId);
	
	//process the other Security Question SelectLists present on the page but not the one the user just changed.
	for ( var count = 0; count < arrayOfQuestionElementIds.length; count++) {
		if (selectListId != arrayOfQuestionElementIds[count]) //only process if its not the SelectList the user just changed
		{
			var objSelectList = document.getElementById(arrayOfQuestionElementIds[count]);
			var objCompleteSelectList = document.getElementById(SOURCE_STANDARD_QUESTIONS_ELEMENT_ID);
			
			//rebuild the SelectList (put it back in its original state with all the options) before removing the options selected by other SelectLists
			rebuildSelectList(objSelectList, objCompleteSelectList);
			
			//remove the options that are already selected by the other SelectLists
			removeOptionsFromSelectList(objSelectList, arrayOfSelectedValues);
		}
	}
}

/*********************************************************************************
Function...:	removeOptionsFromSelectList
Description: 	Removes options from a SelectList object based on the values in the
				arrayOfValuesToRemove array.  It does not remove options with
				value="" as that is reserved for the default value (Select a Security Question...)
returns....: 	void
*********************************************************************************/
function removeOptionsFromSelectList(objSelectList, arrayOfValuesToRemove) {
	//loop through the array of values (options) that need to be removed
	for ( var removeIndex = 0; removeIndex < arrayOfValuesToRemove.length; removeIndex++) {
		var curValueToRemove = arrayOfValuesToRemove[removeIndex];
		//don't remove if the value is "" because that is reserved for the default (Select a security question...)
		//don't remove if the value is "custom" because that is reserved for the custom (Make up your own question...)
		if ((curValueToRemove != "") && (curValueToRemove != CUSTOM_QUESTION)) {
			//loop through the options of the SelectList
			for ( var optionsIndex = 0; optionsIndex < objSelectList.options.length; optionsIndex++) {
				//Remove if it is NOT the selected option AND if the value is in the array of values to remove
				if ((!objSelectList.options[optionsIndex].selected) && (objSelectList.options[optionsIndex].value == curValueToRemove)) {
					objSelectList.options[optionsIndex] = null;
					break; //get out of this loop as the value to be removed will not appear in the SelectList more than once
				}
			}
		}
	}
}

/*********************************************************************************
Function...:	getAllSelectedValues
Description: 	Returns all the selected values of the
				Standard Security Question SelectList objects
returns....: 	Array
*********************************************************************************/
function getAllSelectedValues() {
	//declare an array that will hold the selected values of all the Security Question SelectList elements
	var arrayOfSelectedValues = new Array();
	
	//create an array with the element ids of the Security Question SelectLists
	var arrayOfQuestionElementIds = getArrayOfElementIds(BASE_STANDARD_QUESTION_ELEMENT_ID, NUMBER_OF_SECURITY_QUESTIONS);
	
	for ( var count = 0; count < arrayOfQuestionElementIds.length; count++) {
		arrayOfSelectedValues[count] = document.getElementById(arrayOfQuestionElementIds[count]).value;
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return arrayOfSelectedValues;
}

/*********************************************************************************
Function...:	rebuildSelectList
Description: 	Removes all the options from a Target SelectList and rebuilds
				it from a Source SelectList.  This is done to ensure that SelectLists
				contain the current available options before options are dynamically
				removed based on what is selected in another SelectList object.
returns....: 	void
*********************************************************************************/
function rebuildSelectList(objTargetSelectList, objSourceSelectList) {
	//store the currently selected value
	var selectedValue = objTargetSelectList.value;
	
	//clean out the SelectList
	removeAllOptions(objTargetSelectList);
	
	//copy the options from the "control" or "complete" SelectList which has all the questions
	for ( var count = 0; count < objSourceSelectList.options.length; count++) {
		var objOption = document.createElement("OPTION");
		objOption.text = objSourceSelectList.options[count].text;
		objOption.value = objSourceSelectList.options[count].value;
		objTargetSelectList.options[count] = objOption;
		
		//restore the currently selected option before the rebuild
		if (objOption.value == selectedValue) {
			objTargetSelectList.options[count].selected = true;
		}
	}
}

/*********************************************************************************
Function...:	handleCustomQuestionField
Description: 	Shows or Hides the <div> containing the Custom Question fields
returns....: 	void
*********************************************************************************/
function handleCustomQuestionField(selectListId, customQuestionDivId) {
	var questionValue = document.getElementById(selectListId).value;
	var customQuestionDiv = document.getElementById(customQuestionDivId);
	
	//if the user elected to create their own security question, show the <div> with the Custom Question field
	if (questionValue == CUSTOM_QUESTION) {
		customQuestionDiv.style.visibility = "visible";
		customQuestionDiv.style.display = "block";
	} else {
		customQuestionDiv.style.visibility = "hidden";
		customQuestionDiv.style.display = "none";
	}
}

/*********************************************************************************
Function...:	getArrayOfElementIds
Description: 	Utility function creates an array of Element IDs which takes the
				baseElementId and appends the value of the count to the end of it.
returns....: 	Array
*********************************************************************************/
function getArrayOfElementIds(baseElementId, numberOfElements) {
	var arrayOfElementIds = new Array();
	for ( var count = 0; count < numberOfElements; count++) {
		arrayOfElementIds[count] = baseElementId + (count + 1); //element id values start at 1 so need to add 1 to the counter
	}
	
	/*********************************************************************************
	no code past this point except for the return value
	*********************************************************************************/
	return arrayOfElementIds;
	
}

/*********************************************************************************
Function...:	removeAllOptions
Description: 	Utility function that removes all the options from SelectList object
returns....: 	void
*********************************************************************************/
function removeAllOptions(objSelectList) {
	if (!hasOptions(objSelectList)) {
		return;
	}
	for ( var i = 0; i < objSelectList.options.length; i++) {
		objSelectList.options[i] = null;
	}
	objSelectList.selectedIndex = -1;
}

/*********************************************************************************
Function...:	hasOptions
Description: 	Utility function to check if a SelectList has options in it
returns....: 	boolean
*********************************************************************************/
function hasOptions(objSelectList) {
	if ((objSelectList != null) && (objSelectList.options != null)) {
		return true;
	}
	return false;
}

/*********************************************************************************
Function...:	setValue
Description: 	Utility function to set the value of a Dom element
returns....: 	void
*********************************************************************************/
function setValue(elId, value) {
	if (!isEmpty(elId)) {
		document.getElementById(elId).value = value;
	}
}
/*********************************************************************************
Function...:	isEmpty
Description: 	Utility function to check for empty string
returns....: 	boolean
*********************************************************************************/
function isEmpty(str) {
	if ((str == null) || (ssoTrim(str) == "")) {
		return true;
	} else {
		return false;
	}
}
/***********************************************************
The function submitForm is used to submit the form
that is being passed as parameter.

@author Narayan
***********************************************************/
function submitForm(formName) {
	formName.submit();
}

