﻿// ============================================================================== //
// Gives some indication of the password strength of the specified input field    //
// Do not create this class directly, use as follows:                             //
//     PasswordControl.insert(<password field id>, <wrapper id>,                  //
//                            <table class>, <table style override>,              //
//                            <label class>, <label style override>,              //
//                            <edit class>,  <edit style override>,               //
//                            <onValidStateChanged callback>);                    //
// ============================================================================== //
function PasswordControl(id, onValidStateChanged) {

    // ----------------- //
    // Private variables //
    // ----------------- //
    var charCount = 0;
    var upperCount = 0;
    var numberCount = 0;
    var symbolCount = 0;
    var validState = true;
    updateValidState();
    
    $(id).onkeyup = function() {
        updateCharCounts();
        refreshTextIndicator();
        refreshBarIndicator();
        refreshCharIndicator();
        if ($(id + "Confirm").value != "")
            updatePasswordMatch();
        updateValidState();
    }
    
    $(id).onblur = function() {
        updatePasswordMatch();
    }

    $("passwordConfirm").onkeyup = function() {
        updatePasswordMatch();
        updateValidState();
    }
        
    // --------------- //
    // Private methods //
    // --------------- //
    function updatePasswordMatch() {
        var passwordMatchMessage = "";
        if (!passwordsMatch()) {
            passwordMatchMessage = "Passwords do not match";
            $("pwdNotMatch").show();
        } else {
			$("pwdNotMatch").hide();
        }
        $("pwdNotMatch").innerHTML = passwordMatchMessage;
    }
    
    function passwordsMatch() {
        return $(id).value == $(id + "Confirm").value;
    }
    
    function updateValidState() {
        var oldState = validState;
        var strength = getStrengthCategory()
        if (strength == "Too short") {
            validState = false;
        } else {
            validState = passwordsMatch();
        }
        if (oldState != validState)
            onValidStateChanged(validState);
    }
   
    function updateCharCounts() {
        // Strip all duplicated characters and update the character counts
        var uniqueChars = $(id).value.replace(/(.)(?=.*\1)/g, "");
        charCount  = uniqueChars.length;
        upperCount  = uniqueChars.replace(/[^A-Z]/g, "").length;
        numberCount = uniqueChars.replace(/[^0-9]/g, "").length;
        symbolCount = uniqueChars.replace(/[A-Za-z0-9\s]/g, "").length;
    }
   
    function refreshTextIndicator() {
        var strength = getStrengthCategory()
        $("pwdStrengthTxt").innerHTML = strength;
        $('PasswordMessage').show();
        if (strength == "Best") {
            $("pwdStrengthTxt").style.color = "green";
        } else if (strength == "Strong") {
            $("pwdStrengthTxt").style.color = "green";
        } else if (strength == "Fair") {
            $("pwdStrengthTxt").style.color = "grey";
        } else if (strength == "Weak") {
            $("pwdStrengthTxt").style.color = "red";
        } else {
            $("pwdStrengthTxt").style.color = "grey";
        }
    }
    
    function refreshBarIndicator() {
        var strength = getStrengthCategory()
        if (strength == "Best") {
            $("pwdStrengthBar").style.width = "100%";
            $("pwdStrengthBar").style.backgroundColor = "lime";
        } else if (strength == "Strong") {
            $("pwdStrengthBar").style.width = "100%";
            $("pwdStrengthBar").style.backgroundColor = "green";
        } else if (strength == "Fair") {
            $("pwdStrengthBar").style.width = "75%";
            $("pwdStrengthBar").style.backgroundColor = "gold";
        } else if (strength == "Weak") {
            $("pwdStrengthBar").style.width = "50%";
            $("pwdStrengthBar").style.backgroundColor = "red";
        } else {
            $("pwdStrengthBar").style.width = "25%";
            $("pwdStrengthBar").style.backgroundColor = "grey";
        }
    }
    
    function refreshCharIndicator() {
        $("pwdCharCount").update(
            "length ("      + (sufficientCharCount()   ? "ok" : charCount) + 
            ") - upper ("   + (sufficientUpperCount()  ? "ok" : upperCount) + 
            ") - numbers (" + (sufficientNumberCount() ? "ok" : numberCount) + 
            ") - symbols (" + (sufficientSymbolCount() ? "ok" : symbolCount) + ")"
        );
    }
    
    function getStrengthCategory() {
        var result;
        if (sufficientCharCount() && sufficientUpperCount() && sufficientNumberCount() && sufficientSymbolCount()) {
            result = "Best";
        } else if (sufficientCharCount() && sufficientUpperCount() && sufficientNumberCount()) {
            result = "Strong";
        } else if (sufficientCharCount() && sufficientUpperCount()) {
            result = "Fair";
        } else if (sufficientCharCount()) {
            result = "Weak";
        } else {
            result = "Too short";
        }
        
        $('PasswordStrength').value = result;
        
        return result;
    }
    
    function sufficientCharCount() {
        return charCount >= 6;
    }
    
    function sufficientUpperCount() {
        return upperCount >= 1;
    }
    
    function sufficientNumberCount() {
        return numberCount >= 1;
    }
    
    function sufficientSymbolCount() {
        return symbolCount >= 1;
    }
    
}

// -------------- //
// Static methods //
// -------------- //
PasswordControl.insert = function(id, wrapperId, tableClass, tableStyle, labelClass, labelStyle, editClass, editStyle, onValidStateChanged) {

    // Inject the control
    var tableCss = "class='" + tableClass + "'" + (tableStyle == "" ? "" : " style='" + tableStyle + "'");
    var labelCss = "class='" + labelClass + "'" + (labelStyle == "" ? "" : " style='" + labelStyle + "'");
    var editCss  = "class='" + editClass  + "'" + (editStyle  == "" ? "" : " style='" + editStyle  + "'");
    var col3Css  = "class='" + labelClass + "'" + " style='padding-left:25px; width:180px;" + labelStyle + "'";
    var barCss   = "class='" + labelClass + "'" + " style='height:3px; padding-left:25px; width:180px;" + labelStyle + "'";
    $(wrapperId).innerHTML =
        "<table " + tableCss + ">" +
        "    <tr>" +
        "        <td " + labelCss + ">Your password:</td>" +
        "        <td " + editCss  + "><input id='" + id + "' name='" + id + "' type='password' /></td>" +
        "        <td " + col3Css  + ">Password strength: <span id='pwdStrengthTxt' style='color: gray;'>Too short</span></td>" +
        "    </tr>" +
        "    <tr>" +
        "        <td " + labelCss + " rowspan='2'>Confirm password:</td>" +
        "        <td " + editCss  + " rowspan='2'><input id='" + id + "Confirm' name='" + id + "Confirm' type='password' /></td>" +
        "        <td " + barCss   + "><div id='pwdStrengthBar' style='width: 25%; height: 100%; background-color: gray;'></div></td>" +
        "    </tr>" +
        "    <tr>" +
        "        <td " + col3Css + "><span id='pwdCharCount' style='font-size: 6pt; color: Gray;'>length (0) - upper (0) - numbers (0) - symbols (0)</span></td>" +
        "    </tr>" +
        "    <tr>" +
        "        <td></td>" +
        "        <td " + editCss  + " id='pwdNotMatch' style='font-size: 10pt; color: Red'></td>" +
        "    </tr>" +
        "</table>";
    
    //Instantiate the password control
    return new PasswordControl(id, onValidStateChanged);
    
}

PasswordControl.inveigle = function( id, onValidStateChanged ) {
	return new PasswordControl(id, onValidStateChanged );
}
