/**
 * Text descrambler.
 * http://labs.jodd.org
 */
jQuery.fn.descramble = function(dname) {
	var descramblers = {
		'binary': new RandomCharsDescrambler(['0','1']),
		'hexa': new RandomCharsDescrambler(['1','2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']),
		'l2r': new Left2RightDescrambler()
	};
	if (dname == 'random') {
		var rnd = Math.floor(Math.random() * 3);
		for (d in descramblers) {
			dname = d;
			rnd--;
			if (rnd == 0) break;
		}
	}
	var descrambler = descramblers[dname];
	this.each(function() {
		scrambleAll(this);
		$(this).show();
	});
	return this;
	
	// scrambles all nodes
	function scrambleAll(node) {
		$(node).contents().each(function() {
			scrambleAll(this);
			if (this.nodeType == 3) {
				if (hasChars(this.nodeValue)) {
					var text = this.nodeValue;
					this.nodeValue = descrambler.scramble(text);
					descrambler.reveal(this, text);
				}
			}
		});
	}
	
	// returns non-zero value if string has non-whitespace characters.
	var reg = new RegExp("\r|\n| |\t", "g");
	function hasChars(s) {
		s = s.replace(/^\s+|\s+$/g, ''); //trim
		s = s.replace(reg, '');
		return s.length;
	}
};


/**
 * Chars descrambler.
 */
function RandomCharsDescrambler(mychars) {
	this.chars = mychars;
	
	this.scramble = function(text) {
		result = "";
		for (j = 0; j < text.length; j++) {
			rnd = Math.floor(Math.random() * this.chars.length);
			result += this.chars[rnd];
		}
		return result;
	}
	
	this.reveal = function(node, text) {
		var arr = randomIndexes(text.length);
		setTimeout(function(){revealText(node, text, arr, 0);}, 2500);
	}
	function revealText(node, text, arr, count) {
		if (count == text.length) {
			return;
		}
		var ndx = arr[count];
		var msg = node.nodeValue;
		node.nodeValue = msg.substring(0, ndx) + text.substring(ndx, ndx + 1) + msg.substring(ndx + 1);
		var speed = 30;
		if (count < 10) {	// first 10 loops do slower
			speed = 100;
		}
		count++;
		setTimeout(function(){revealText(node, text, arr, count);}, speed);
	}
	
	// creates array of random indexes
	function randomIndexes(len) {
		var arr = new Array();
		var j = 0;
		for (j = 0; j < len; j++) {		// create sorted series
			arr[j] = j;
		}
		
		// randomize elements in series
		j = 0;
		while (j < len) {
			var rnd = Math.floor(Math.random() * len);
			if (rnd != j) {
				var x = arr[j];
				arr[j] = arr[rnd];
				arr[rnd] = x;
			}
			j++;
		}
		return arr;
	}
};

/**
 * Left2Right descrambler.
 */
function Left2RightDescrambler() {
	
	this.scramble = function(text) {
		result = "";
		for (j = 0; j < text.length; j++) {
			result += '_';
		}
		return result;
	}
	
	this.reveal = function(node, text) {
		setTimeout(function(){revealText(node, text, 0);}, 2500);
	}
	function revealText(node, text, count) {
		if (count > text.length) {
			return;
		}
		var msg = node.nodeValue;
		node.nodeValue = text.substring(0, count) + msg.substring(count);
		var speed = 30;
		if (count < 10) {	// first 10 loops do slower
			speed = 100;
		}
		count++;
		setTimeout(function(){revealText(node, text, count);}, speed);
	}
};

