/* ##################################################################

This Class is a prototype of a new way to implement captcha
in web forms.

It creates a verification proccess throught a key board
key sequence.

This Class uses function to encode and decode a string in base 64.
This function was built by Danny Goodman (http://www.dannyg.com).

Developed by Nelson Conceição (Latitudes) - nelson@latitudes.pt
Idea by Mário Andrade (Latitudes) - marioandrade@latitudes.pt

################################################################## */


var Captcha = Class.create({
	
	initialize: function(targetElement){
		//define vars
		this.allowedCodes 				= [17, 37, 38, 39, 40];
		
		this.codes_arr 						= [];
		this.array_pos 						= 0;
		this.validated 						= false;
		this.timer 								= null;
		this.captchaContainer 		= targetElement;
		this.statusContainer			= 'captcha_status_container';
		this.statusBox						= 'captcha_status';
		
		this.themePath						= "/wp-content/themes/latitudes";
		
		//base 64 lists
		this.enc64List 						= [];
    this.dec64List 						= [];
		
		//generate codes
		this.generateCodes();
		
		//draw captcha box when DOM is completly loaded
		Event.observe(document, 'dom:loaded', (function(){
			this.drawBox();
		}).bind(this));
		
	},
	
	drawBox: function(){
		//build captcha content
		var captchaContent = '<p>Clique em <i>Executar Verificação</i> e execute a seguinte combinação de teclas:</p>' +
												 '<p style="margin-top:7px;" class="images_label">';
		for(i = 0; i < this.codes_arr.length; i++){
			captchaContent += '<img src="' + this.themePath + '/js/captcha/images/' + this.codes_arr[i] + '.png" />';
		}
		captchaContent += '</p>' +
											'<p style="margin-top:7px;"><a id="captcha_look"><img src="' + this.themePath + '/js/captcha/images/verify_btn.png" /></a></p>' +
											'<p style="margin-top:7px; display:none;" id="captcha_status_container"><b>Estado:</b> <span id="captcha_status" class="yellow">A aguardar digitação!</span></p>' +
											'<input type="hidden" name="captcha_validation" id="captcha_validation" />';
		//insert captcha content to container
		$(this.captchaContainer).innerHTML = captchaContent;
		//add listeners
		this.addListeners();
	},
	
	addListeners: function(){
		//add event observers
		Event.observe($('captcha_look'), 'click', (function(){
			$(this.statusContainer).style.display = "";
			Event.observe(document, 'keydown', (function(event){
					event.preventDefault();
			}).bind(this));
			Event.observe(document, 'keyup', (function(event){
				this.check(event);
			}).bind(this));
		}).bind(this));
	},
	
	generateCodes: function(){
		if(this.codes_arr.length == 0){
			for(i = 0; i < 5; i++){
				this.codes_arr.push(this.allowedCodes[Math.floor(Math.random() * this.allowedCodes.length)]);
			}
		}
		this.saveCodes();
	},
	
	saveCodes: function(){
		var url = this.themePath + "/js/captcha/savecodes.php";
		var params = {codes: this.codes_arr.join("")};
		new Ajax.Request(url, {
			parameters: params,
			method: 'post',
			onSuccess: function(transport){
				if(transport.responseText == 'erro'){
					alert("Ocorreu um erro! Recarregue a página.");
				}
			}
		});
	},
	
	clear: function(){
		array_pos = 0;
		$('captcha_status').className = 'red';
		$('captcha_status').innerHTML = "Tem de ser mais rápido! Recomece.";
	},
	
	check: function(e){
		if(this.validated == false){
			var unicode = (window.event) ? event.keyCode : ((e.charCode) ? e.charCode : e.keyCode);
			if(unicode == this.codes_arr[this.array_pos]){
				$('captcha_status').className = 'green';
				$('captcha_status').innerHTML = "OK";
				clearTimeout(this.timer);
				if(this.array_pos >= this.codes_arr.length - 1){
					this.validated = true;
					$('captcha_status').className = 'green';
					$('captcha_status').innerHTML = "Verificado.";
					$('captcha_validation').value = this.base64Encode(this.codes_arr.join(''));
					document.stopObserving('keyup');
					document.stopObserving('keydown');
				} else {
					this.timer = setTimeout(this.clear, 3000);
				}
				this.array_pos++;
			} else {
				this.array_pos = 0;
				$('captcha_status').className = 'red';
				$('captcha_status').innerHTML = "Errado! Recomece.";
			}
		}
	},
	
	verify: function(){
		if($('captcha_validation').value != "" && this.base64Decode($('captcha_validation').value) == this.codes_arr.join('')){
			return true;
		} else {
			return false;
		}
	},
	
	// base64 by Danny Goodman //
	
	initBase64: function(){
		
		var i;
		for (i = 0; i < 26; i++) {
			this.enc64List[this.enc64List.length] = String.fromCharCode(65 + i);
		}
		for (i = 0; i < 26; i++) {
			this.enc64List[this.enc64List.length] = String.fromCharCode(97 + i);
		}
		for (i = 0; i < 10; i++) {
			this.enc64List[this.enc64List.length] = String.fromCharCode(48 + i);
		}
		this.enc64List[this.enc64List.length] = "+";
		this.enc64List[this.enc64List.length] = "/";
		for (i = 0; i < 128; i++) {
			this.dec64List[this.dec64List.length] = -1;
		}
		for (i = 0; i < 64; i++) {
			this.dec64List[this.enc64List[i].charCodeAt(0)] = i;
		}
	},
	
	base64Encode: function(str){
		var c, d, e, end = 0;
    var u, v, w, x;
    var ptr = -1;
    var input = str.split("");
    var output = "";
    while(end == 0) {
        c = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) : 
            ((end = 1) ? 0 : 0);
        d = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) : 
            ((end += 1) ? 0 : 0);
        e = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) : 
            ((end += 1) ? 0 : 0);
        u = this.enc64List[c >> 2];
        v = this.enc64List[(0x00000003 & c) << 4 | d >> 4];
        w = this.enc64List[(0x0000000F & d) << 2 | e >> 6];
        x = this.enc64List[e & 0x0000003F];
        
        // handle padding to even out unevenly divisible string lengths
        if (end >= 1) {x = "=";}
        if (end == 2) {w = "=";}
        
        if (end < 3) {output += u + v + w + x;}
    }
    // format for 76-character line lengths per RFC
    var formattedOutput = "";
    var lineLength = 76;
    while (output.length > lineLength) {
      formattedOutput += output.substring(0, lineLength) + "\n";
      output = output.substring(lineLength);
    }
    formattedOutput += output;
    return formattedOutput;
	},
	
	base64Decode: function(str){
		var c = 0, d = 0, e = 0, f = 0, i = 0, n = 0;
    var input = str.split("");
    var output = "";
    var ptr = 0;
    do {
			f = input[ptr++].charCodeAt(0);
			i = this.dec64List[f];
			if (f >= 0 && f < 128 && i != -1) {
				if ( n % 4 == 0 ) {
					c = i << 2;
				} else if ( n % 4 == 1 ) {
					c = c | ( i >> 4 );
					d = ( i & 0x0000000F ) << 4;
				} else if ( n % 4 == 2 ) {
					d = d | ( i >> 2 );
					e = ( i & 0x00000003 ) << 6;
				} else {
					e = e | i;
				}
				n++;
				if ( n % 4 == 0 ) {
					output += String.fromCharCode(c) + 
										String.fromCharCode(d) + 
										String.fromCharCode(e);
				}
			}
    }
    while (typeof input[ptr] != "undefined");
    output += (n % 4 == 3) ? String.fromCharCode(c) + String.fromCharCode(d) : 
              ((n % 4 == 2) ? String.fromCharCode(c) : "");
    return output;
	}
	
	// ##base64 by Danny Goodman //

});
