/**
 * @author Dave Nagrocki 12/10/2009
 *
 * Adds a password Strength progress bar and icon grid determining if the password
 * the user types is strong enough to use.
 *
 * To use, add a Span tag in the jsp as to where you want this to appear and give it an ID. 
 * All html this js writes will be within the span tag
 *	
 *		<span id="messageField" ></span>
 * 
 * In your password input box add the following event with the id of the span tag and password field
 * to check as strings to the checkPassword method. Also, specify if the layout is vertical by specifying true or false
 *
 *		onkeyup="checkPassword('passwordbox','messageField',true);"
 *
 * You also must call the loadPasswordStrength('messageField', true) method within the onload event in the <Body> tag.
 * This will create the initial grid and progress bar when the page is loaded.  If the user doesn't have javascript 
 * enabled, this functionality will not show. You must specify the layout as vertical or not by adding true or false to the method.
 *
 * There are some style sheet entries needed.  These are for the icons and table design.
 * I had to put mine in the jsp since inheritance of the css tables was making table borders show
 * up where I did not want them to. So if you want to avoid this add the following to the jsp. 
 * Dont forget the image locations either.
 *	
 *	<style type="text/css">
 *		#passwordCriteria ul { font:Arial, Helvetica, sans-serif; margin-left:0px; padding-left:0px; }
 * 		.good { list-style-image:url(../images/pwGood.gif); color:#999999; }
 * 		.bad { list-style-image:url(../images/pwBad.gif); color:#000; }
 * 
 * 		.datatableSimple {border:none; border-collapse: collapse; }
 *		.datatableSimple td { border:none; padding: 2px; }
 *		.datatableSimple th { border:none; }
 *		.datatableSimple td.left { border-left-color: #B47020; border-left-width: 1px; border-left-style: solid; }
 *		.datatableSimple th.left { border-left-color: #B47020; border-left-width: 1px; border-left-style: solid; }
 *	</style>
 *
 */

//This is the DEFAULT length...it may be overridden later with parameters passed in from the user
var Password_Length_Minimum = 9;

/* Loads the password strength section initially allowing for it not to show up if
 * the user does not have javascript enabled.
 * Pass in the name of the SPAN tag where the table should be written initially
 */
function loadPasswordStrength(messageField,layoutVertical,minLength){

	var message = document.getElementById(messageField);	
	var numsIcon = "bad";
	var specIcon = "bad";
	var lcaseIcon = "bad";
	var ucaseIcon = "bad";
	var charsIcon = "bad";
	var excludedIcon = "good";
	
	//Set the min password length from parameters passed from user
	Password_Length_Minimum = minLength;
	
	if (message){
		//Load the section
		message.innerHTML = buildSection(minLength, ucaseIcon, lcaseIcon, numsIcon, specIcon, Password_Length_Minimum, charsIcon, 0,layoutVertical, excludedIcon, "");
	}
}

/* Checks the password based on all of the password strength criteria
 * Pass in the name of the password field to check and the name of the SPAN tag
 * and where the information will be written to.
 */
function checkPassword(passwordField, messageField, layoutVertical,minLength) 
{
	//Set the min password length from parameters passed from user
	Password_Length_Minimum = minLength;

	var description = new Array();
	var password = document.getElementById(passwordField);
	var message = document.getElementById(messageField);		
	var passwordValue = password.value;
	
	var reqsMet = true;
	var remain = "";
	var counter = 0;
	var x = 0;
		
	var charsLeft = Password_Length_Minimum;
	var charsIcon = "bad";
	
	var numsLeft = 2;
	if(Password_Length_Minimum == 9){
		numsLeft = 1;
	}
	var numsIcon = "bad";
	
	var specLeft = 2;
	if(Password_Length_Minimum == 9){
		specLeft = 1;
	}
	var specIcon = "bad";
	
	var lcaseLeft = 2;
	if(Password_Length_Minimum == 9){
		lcaseLeft = 1;
	}
	var lcaseIcon = "bad";
	
	var ucaseLeft = 2;
	var ucaseIcon = "bad";
	if(Password_Length_Minimum == 9){
		ucaseLeft = 0;
	}
	
	
	var excludedChars = "";
	var excludedIcon = "good";

	var passwordLength = 0;
	
	if(password && message && passwordValue)
	{
		counter = 0;
	
		//Loop through the password
		for (x=0;x<=passwordValue.length -1;x++)
		{
			passwordLength++;
			var t = passwordValue.charAt(x);
			//The isNaN thinks a " " (space) is a number, so we must fix that
			if (t == " " || isNaN(t)){
				//not a number
				var value = passwordValue.charAt(x)
				
				//Check special
				if (isSpecial(value)){
					specLeft = specLeft - 1;
				}
				
				//Check upper
				if (isUpper(value)){
					 ucaseLeft = ucaseLeft - 1;
					 if(Password_Length_Minimum == 9){
					 	//We don't care about case for non admins, so manage all letters in lcaseLeft.
						lcaseLeft = lcaseLeft - 1;
					}
				}
				
				//Check lower
				if (isLower(value)){
					lcaseLeft = lcaseLeft - 1;
				}
				
				//Check Excluded
				if (isExcluded(value)){
					passwordLength--;
					if (value == " "){
						value = "space";
					}
					//Check if the value is already there to not add it twice
					if (excludedChars.indexOf(value) == -1){
						excludedChars = excludedChars + value;
					}
				}
			}
			else{
				//it is a number
				numsLeft = numsLeft -1;
			}
			
		}
		
		//Figure out how many characters are left
		if(passwordLength < Password_Length_Minimum)
		{
			charsLeft = Password_Length_Minimum - passwordLength;
		}
		else
		{
			//Characters met is valid
			counter++;
			charsLeft = 0;
			charsIcon = "good";
		}
		
				
		//Get the progress bar values
		if (specLeft <= 0){
			counter++;	
			specIcon = "good";	
		}
		if (ucaseLeft <= 0){
			counter++;	
			ucaseIcon = "good";	
		}
		if (lcaseLeft <= 0){
			counter++;
			lcaseIcon = "good";		
		}
		if (numsLeft <= 0){
			counter++;	
			numsIcon = "good"; 	
		}
		if (excludedChars != ""){
			excludedIcon = "bad"; 	
		}
		else{
			counter++;
		}
		
		if (counter<0){
			counter = 0;
		}
						
	}
	//Write the info out to the span tag
	message.innerHTML = buildSection(Password_Length_Minimum, ucaseIcon, lcaseIcon, numsIcon, specIcon, charsLeft, charsIcon, counter, layoutVertical, excludedIcon, excludedChars);
	
}

/* Builds the progress bar with the proper percentage.  
 *  It currently displays in 20% increments since we have 5 checks since 100/5 = 20
 */
function buildProgressBar(percentageValue){

	//Write out progress bar and other html
	var description = new Array();
	
	//0%
	description[0] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td class=tinytext height=15 width=150 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//16.6%	
	description[1] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td height=15 width=25 bgcolor=#ff0000></td><td height=15 width=125 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//33.2%
	description[2] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td height=15 width=50 bgcolor=#bb0000></td><td height=15 width=100 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//49.8%
	description[3] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td height=15 width=75 bgcolor=#ff9900></td><td height=15 width=75 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//66.4%
	description[4] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td height=15 width=100 bgcolor=#CC6600></td><td height=15 width=50 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//83%
	description[5] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=2><tr><td height=15 width=125 bgcolor=#EAFF00></td><td height=15 width=25 bgcolor=#dddddd></td></tr></table></td></tr></table>";
	//100%
	description[6] = "<table border=0 cellpadding=0 cellspacing=0><tr><td>Strength:</td><td><table cellpadding=0 cellspacing=0><tr><td class=tinytext height=15 width=150 bgcolor=#00ee00 align=center><font color=#FFFFFF>Password Valid</font></td></tr></table></td></tr></table>";
	
	return description[percentageValue];

}

/* Build the explanation table section by passing the proper icon style in (bad/good, characters left
 * and the percent progress that needs to be displayed on the progress bar.
 */
function buildSection(minLength, ucaseIcon, lcaseIcon, numsIcon, specIcon, charsLeft, charsIcon, percentProgress, layoutVertical, excludedIcon, excludedChars){

	//Load the section
	var resultTable = "";
       
    resultTable += "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"datatableSimple\"><tr>";
    resultTable += "<td height=\"30\" colspan=\"2\" valign=\"middle\">" + buildProgressBar(percentProgress) + "</td></tr><tr>";
    resultTable += "<td colspan=\"2\" valign=\"middle\" nowrap>";
   	resultTable += "<ul id=\"passwordCriteria\"><li class=" + excludedIcon + ">Invalid characters found: " + excludedChars + "</li>";
   	resultTable += "<li class=" + charsIcon + ">Minimum characters remaining: " + charsLeft + "</li>";
    
    
    if (layoutVertical == true && minLength > 9){
    	//Vertical Layout - admin
    	resultTable += "<li class=" + ucaseIcon + ">2 uppercase letters</li><li class=" + lcaseIcon + ">2 lowercase letters</li>";
       	resultTable += "<li class=" + numsIcon + ">2 numbers</li><li class=" + specIcon + ">2 special characters</li></ul></td>";
    }
    else if(minLength > 9){
    	//Horizontal layout - admin
        resultTable += "</ul></td></tr><tr><td valign=\"middle\" nowrap>";
   		resultTable += "<ul id=\"passwordCriteria\"><li class=" + ucaseIcon + ">2 uppercase letters</li><li class=" + lcaseIcon + ">2 lowercase letters</li>";
       	resultTable += "</ul></td><td valign=\"middle\" nowrap><ul id=\"passwordCriteria2\"><li class=" + numsIcon + ">2 numbers</li><li class=" + specIcon + ">2 special characters</li></ul></td>";
	}else if (layoutVertical == true && minLength == 9){
		//Vertical Layout - non admin
    	resultTable += "<li class=" + lcaseIcon + ">1 letter</li>";
       	resultTable += "<li class=" + numsIcon + ">1 number</li><li class=" + specIcon + ">1 special character</li></ul></td>";
	}else{
		//Horizontal layout - non admin
        resultTable += "</ul></td></tr><tr><td valign=\"middle\" nowrap>";
   		resultTable += "<ul id=\"passwordCriteria\"><li class=" + lcaseIcon + ">1 letter</li><li class=" + numsIcon + ">1 number</li>";
       	resultTable += "</ul></td><td valign=\"middle\" nowrap><ul id=\"passwordCriteria2\"><li class=" + specIcon + ">1 special character</li></ul></td>";
	
	}
	
   	resultTable += "</tr></table>";
	
	return resultTable;
}

function isLower(ch) { 
	var lowers; 
	lowers = "abcdefghijklmnopqrstuvwxyz"; 
	return (lowers.indexOf(ch) != -1); 
} 
function isUpper(ch) {
	var uppers; 
	uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
	return (uppers.indexOf(ch) != -1); 
} 
function isSpecial(ch) {
	var specials; 
	specials = "#$%&_-"; 
	return (specials.indexOf(ch) != -1); 
} 
function isExcluded(ch) {
	var excluded; 
	excluded = "()<>+*/=?!,.:;@'\"` []{}^\\|~"; 
	return (excluded.indexOf(ch) != -1); 
} 
function negativeMakeZero(ch) {
	if (ch < 0){
		return 0;
	}
	else{
		return ch;
	}
} 
