define("entropy",['jquery'],function($){

    /**
     * Determine the size of the character pool used in a password. Useful to calculate password entropy
     * param password: The password to analyze
     * returns: int
     */
    function CharPoolSize(password)
    {
        if ((undefined === password) || (null === password)) {
            return 0;
        }
        var re_digits       = new RegExp("[0-9]+");
        var re_lowercase    = new RegExp("[a-z]+");
        var re_uppercase    = new RegExp("[A-Z]+");
        var re_specialchars = new RegExp("[\W_ ]+");
        var n_options = 0;
        if(password.match(re_digits)) // check numbers
            n_options += 10;
        if(password.match(re_lowercase)) // check lowercase
            n_options += 26;
        if(password.match(re_uppercase)) // check
            n_options += 26;
        if(password.match(re_specialchars)) // check specialchars
            n_options += 32;
        return n_options;
    }

    /**
     * Determine the number of unique characters in a string. Useful to calculate password entropy</description>
     * returns: int
     * param str:   The string to analyze
     */
    function CountUniqueChars(str)
    {
        var characters = new Array();
        var count = 0;
        var length= str.length;
        var x;

        //loop, figure it out
        for(x = 0; x < length; x++) {
        var c = str.charAt(x)
        if($.inArray(c,characters) == -1)
        {
            characters.push(c);
            count += 1;
        }
        }
        return count;
    }

    /**
     * Calculate the entropy of a series of tokens (in bits)</description>
     * returns : float
     * param length: The length of the token series
     * param poolsize: The size of the token pool from which the tokens are picked
     */
    function CalculateEntropy(length,poolsize)
    {
        if ((undefined === poolsize) || (null === poolsize) || (0 === poolsize))
        {
            return 0; // entropy per char would be NaN, we take that as 0, and length * 0 is 0 bits of entropy
        }
        if(poolsize == 1) // on a pool size of one, the calculation is similar to the base2log of the length, since we have to attempt [length] times to get there
        {
            return (Math.log(length)/Math.LN2); //base2log(length);
        }

        return length * (Math.log(poolsize)/Math.LN2); //length * base2log(poolsize);
    }

    let my = {
        calculate: function(password)
        {
            let base = CharPoolSize(password);
            return CalculateEntropy(password.length,base);
        },
    };
    return my;

});

