// Password strength meter

// This jQuery plugin is based on the Password Strength Meter 2 (https://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/)
// written by Firas Kassem [2007.04.05] and modified by Amin Rajaee [2009.07.26]   // Firas Kassem  phiras.wordpress.com (phiras at gmail {dot} com),  Amin Rajaee  (rajaee at gmail {dot} com)
// is was licensed under Creative Commons 3.0 Attribution Unported license http://creativecommons.org/licenses/by/3.0/.    
// Thanks guys!!   

// for more information : http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/

var PERCENT_TOO_SHORT = -1;
var PERCENT_TOO_LONG = -2;
var PERCENT_SAME_AS_USERNAME = -3;
var PERCENT_INVALID = 0;

var TEXT_TOO_SHORT = 'Too short';
var TEXT_TOO_LONG = 'Too long';
var TEXT_INVALID_PASSWORD = 'Invalid';
var TEXT_BAD_PASSWORD = 'Weak';
var TEXT_GOOD_PASSWORD = 'Medium';
var TEXT_STRONG_PASSWORD = 'OK';
var TEXT_SAME_AS_USERNAME = 'Same as username';

var TITLE_TOO_SHORT = 'Password must be at least 6 characters long';
var TITLE_TOO_LONG = 'Password must not be longer than 16 characters';
var TITLE_INVALID_PASSWORD = 'Password must contain at least one digit and one letter';
var TITLE_BAD_PASSWORD = 'Use letters, numbers, mixed case or special characters';
var TITLE_GOOD_PASSWORD = 'Use special Characters';

var ERROR_MAP = new Object();
ERROR_MAP[PERCENT_TOO_SHORT] = TEXT_TOO_SHORT;
ERROR_MAP[PERCENT_TOO_LONG] = TEXT_TOO_LONG;
ERROR_MAP[PERCENT_INVALID] = TEXT_INVALID_PASSWORD;
ERROR_MAP[PERCENT_SAME_AS_USERNAME] = TEXT_SAME_AS_USERNAME;

var TITLE_MAP = new Object();
TITLE_MAP[TEXT_TOO_SHORT] = TITLE_TOO_SHORT;
TITLE_MAP[TEXT_TOO_LONG] = TITLE_TOO_LONG;
TITLE_MAP[TEXT_INVALID_PASSWORD] = TITLE_INVALID_PASSWORD;
TITLE_MAP[TEXT_BAD_PASSWORD] = TITLE_BAD_PASSWORD;
TITLE_MAP[TEXT_GOOD_PASSWORD] = TITLE_GOOD_PASSWORD;

jQuery(document).ready(function()
{

    var password = jQuery('input#password').val();

    if(password != null && password != '')
        updatePassword();

});

function updatePassword()
{
    var password = jQuery('input#password').val();
    var username = '';
    var percent = passwordStrengthPercent(password, username);
    var result = passwordStrength(percent);

    if(percent < 0)
        percent = 0;
    
    jQuery('span.percent').html(percent + '%');
    jQuery('span.result').html(result);

    var title = TITLE_MAP[result];

    if(title == null)
        jQuery('span.passwordStrength').removeAttr('title');
    else
        jQuery('span.passwordStrength').attr('title', title);

    var width = jQuery('div.percentBackground').width();
    jQuery('div.percentBar').width(width * percent / 100);
    jQuery('div.percentBar').css('background-position', '0% ' + percent + '%');
}

//var tooLongPass = 'Password must be 16 characters or less'
//var shortPass = 'Password too short';
//var badPass = 'Weak Password - Use letters, numbers, mixed case or special characters';
//var goodPass = 'Medium - Use special characters';
//var strongPass = 'OK';
//var sameAsUsername = 'Password is the same as username.';

function passwordStrength(score)
{
    var result = ERROR_MAP[score];

    if(result != null)
        return result;
    
    if(score < 34)
        return TEXT_BAD_PASSWORD;

    if(score < 68)
        return TEXT_GOOD_PASSWORD;
    
    return TEXT_STRONG_PASSWORD;
}


function passwordStrengthPercent(password, username)
{
    var score = 0;

    if(password.length < 6)
        return PERCENT_TOO_SHORT;

    if(password.length > 16)
        return PERCENT_TOO_LONG;

    //password == username
    if(password.toLowerCase() == username.toLowerCase())
        return PERCENT_SAME_AS_USERNAME;

    // password must contain letters and numbers
    if(!password.match(/([a-zA-Z])/) || !password.match(/([0-9])/))
        return PERCENT_INVALID;

    //password length
    score += password.length * 6;
    score += checkRepetition(1, password).length - password.length;
    score += checkRepetition(2, password).length - password.length;
    score += checkRepetition(3, password).length - password.length;
    score += checkRepetition(4, password).length - password.length;

    //password has 2 numbers
    if(password.match(/(.*[0-9].*[0-9].*[0-9])/))
        score += 10;

    //password has 4 numbers
    //if (password.match(/(.*[0-9].*[0-9].*[0-9].*[0-9])/) && password.length<9)  score += 10 

    //password has 2 symbols
    if(password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/))
        score += 20;

    //password has Upper and Lower chars
    if(password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))
        score += 25;

    //password has number and chars
    if(password.match(/([a-zA-Z])/) && password.match(/([0-9])/))
        score += 35;

    //password has number and symbol
    if(password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/))
        score += 35;

    //password has char and symbol
    if(password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/))
        score += 35;

    //password is just a nubers or chars
    if(password.match(/^\w+$/) || password.match(/^\d+$/))
        score -= 20;

    if(score < 0)
        return 0;

    if(score > 100)
        return 100;
    
    return score;
}

// checkRepetition(1,'aaaaaaabcbc')   = 'abcbc'
// checkRepetition(2,'aaaaaaabcbc')   = 'aabc'
// checkRepetition(2,'aaaaaaabcdbcd') = 'aabcd'

function checkRepetition(pLen, str)
{
    var res = "";

    for(var i = 0; i < str.length; i++)
    {
        var repeated = true;

        for(var j = 0; j < pLen && (j + i + pLen) < str.length; j++)
            repeated = repeated && (str.charAt(j + i) == str.charAt(j + i + pLen));

        if(j < pLen)
            repeated = false;

        if(repeated)
        {
            i += pLen - 1;
            repeated = false;
        }
        else
        {
            res += str.charAt(i);
        }
    }
    
    return res;
}

