/**
 * Password Strength Meter, developed for AirTight.  Uses the core strength algorithm
 * from Darren Mason's plugin (http://plugins.jquery.com/node/7000), but provides 
 * better UI options and more flexibility in implementation.
 */

jQuery.fn.passwordmeter = function(options){
	
	var methods = {
		init: function(){
			options.onInit.call(this, options);
			this.css('background', '#'+options.colorLimits.low).bind('keyup', function(){
				score = methods.getStrength.call($(this));
				color = methods.applyScoreColor.call($(this), score);
				strength = methods.getStrengthString(score);
				options.onKeyup.call($(this), strength, score, color, options);
			});
		},
		applyScoreColor: function(score){
			var hex = methods.getScoreColor(score);
			this.css('background', '#'+hex);
			return hex;
		},
		getScoreColor: function(score){
			score = score / options.standards.high;
			dec = [];
			for (var i=0;i<3;i++) {
				var base = options.colorLimitsDec.low[i];
				var range = options.colorLimitsDec.high[i] - options.colorLimitsDec.low[i];
				var diff = range * score;
				var calc = Math.round(base + diff);
				dec.push(calc);
			}
			// and finally, convert to hex
			hex = methods.toHex(dec);
			return hex;
		},
		getStrength: function(){
			var score = 0; 
			var password = this.val();
	    
		    //password length
		    score += password.length * 4;
		    score += ( methods.checkRepetition(1,password).length - password.length ) * 1;
		    score += ( methods.checkRepetition(2,password).length - password.length ) * 1;
		    score += ( methods.checkRepetition(3,password).length - password.length ) * 1;
		    score += ( methods.checkRepetition(4,password).length - password.length ) * 1;

		    //password has 3 numbers
		    if (password.match(/(.*[0-9].*[0-9].*[0-9])/)){ score += 5;} 
	    
		    //password has 2 symbols
		    if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)){ score += 5 ;}
	    
		    //password has Upper and Lower chars
		    if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)){  score += 10;} 
	    
		    //password has number and chars
		    if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/)){  score += 15;} 
		    //
		    //password has number and symbol
		    if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/)){  score += 15;} 
	    
		    //password has char and symbol
		    if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/)){score += 15;}
	    
		    //password is just a numbers or chars
		    if (password.match(/^\w+$/) || password.match(/^\d+$/) ){ score -= 10;}
	    
		    //verifying 0 < score < 100
		    if ( score < options.standards.low ){score = options.standards.low;} 
		    if ( score > options.standards.high ){  score = options.standards.high;}
	    
			return score;
		},
		getStrengthString: function(score) {
			var strength = 'Weak';
			jQuery.each(options.strengthStrings, function(key, value){
				if (score >= this[0] && score <= this[1]) {
					strength = key;
				}
			});
			return strength;
		},
		checkRepetition: function(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;
		},
		convertColors: function(colors) {
			var limitsDec = {};
			jQuery.each(colors, function(key, val){
				limitsDec[key] = methods.toDec(val);
			});
			return limitsDec;
		},
		toDec: function(hex){
			hexArray = hex.match(RegExp('.{1,2}','g'))
			dec = [];
			$.each(hexArray, function(){
				dec.push(Number(parseInt(this, 16).toString(10)));
			});
			return dec;
		},
		toHex: function(dec){
			hexArr = [];
			$.each(dec, function(){
				hexArr.push(parseInt(this, 10).toString(16));
			});
			return hexArr.join('');
		}
	}
	
	var defaults = {
		colorLimits: {
			low: 'FFEBE8',
			high: 'CEE6C3'
		},
		standards: {
			low: 0,
			high: 70
		},
		strengthStrings: {
			Weak: [0,25],
			Good: [26, 55],
			Strong: [56, 70]
		},
		onInit: function(){},
		onKeyup: function(){}
	};
	options = $.extend(defaults, options);
	options.colorLimitsDec = methods.convertColors(options.colorLimits);
	
	this.each(function(){
			methods.init.call($(this));
		});
	return this;
	
}
