JSSeguranca = new Class({

	primosArray: null,
	clientKey: null,

	// ----------------------------------------------------------------------------------------------------
	initialize: function(l) {

		this.primosArray = new Array(3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37);

		$('a_logo').addEvent('click', function(event) {
			var event = new Event(event);
			if(event.shift && (event.control || event.alt)) {
				event.stop();
				document.location.href = '?l=' + l + '&p=autenticar';
			}
		});

		Number.prototype.toHexStr = function() {
			var s="", v;
			for (var i=7; i>=0; i--) {
				v = (this>>>(i*4)) & 0xf; s += v.toString(16);
			}
			return s;
		}

	},

	// ----------------------------------------------------------------------------------------------------
	verificaLogin: function() {

		$('nome_utilizador').disabled = $('palavra_passe_pre').disabled = $('btn_submit').disabled = true;
		$('btn_submit').value = 'Aguarde...';

		// Determinar a chave da sessao
		this.diffieHellman();

		// Codificar
		$('palavra_passe').value = this.codifica($('palavra_passe_pre').value);

		new Request.HTML({
			url: 'modulos/seguranca/verificar_login.ajax.php',
			onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
				$('nome_utilizador').disabled = $('palavra_passe_pre').disabled = $('btn_submit').disabled = false;
				if(responseHTML == '1') {	// Correcta
					$('form_login').submit();
				} else {					// Errada
					$('btn_submit').value = 'Autenticar';
					$('form_login').setStyle('marginLeft', 10);
					new Fx.Tween('form_login', {
						duration: 'short',
						transition: 'elastic:out'
					}).start('marginLeft', 0);
				}
			}
		}).post({
			nome_utilizador: $('nome_utilizador').value,
			palavra_passe: $('palavra_passe').value
		});

	},

	// ----------------------------------------------------------------------------------------------------
	diffieHellman: function() {

		var getPrimitiveRoots =  function(p) {
			var o = 1;
			var k;
			var primitiveRoots = new Array();
			for (var r = 2; r < p; r++) {
				k = Math.pow(r, o);
				k %= p;
				while(k > 1) {
					o++;
					k *= r;
					k %= p;
				}
				if(o == p - 1) primitiveRoots.push(r);
				o = 1;
			}
			return primitiveRoots;
		}
		getRandomArrayMember = function(array) {
			return array[Math.round(Math.random() * (array.length - 1))];
		}
		getRandomIntegerBetween = function(a, b) {
			return Math.round(Math.random() * (b - a) + a);
		}

		var a, g, p, A, primitiveRoots;
		a = getRandomIntegerBetween(2, 10);
		p = getRandomArrayMember(this.primosArray);
		primitiveRoots = getPrimitiveRoots(p);
		g = getRandomArrayMember(primitiveRoots);
		A = Math.pow(g, a) % p;

		gpARequest = new Request.JSON({
			url: 'modulos/seguranca/diffie_hellman.ajax.php',
			async: false,
			onSuccess: function(info) {
				seguranca.clientKey = Math.pow(info.B, this.a) % this.p;
			}
		});
		gpARequest.a = a;
		gpARequest.p = p;
		gpARequest.get({g: g, p: p, A: A});

	},

	// ----------------------------------------------------------------------------------------------------
	codifica: function(s) {

		return this.sha1(this.sha1(s) + this.clientKey);

	},

	// ----------------------------------------------------------------------------------------------------
	verificaAlterarAcesso: function() {

		// Validar no servidor
		new Request.JSON({
			url: 'modulos/seguranca/alterar_acesso.ajax.php',
			async: true,
			onSuccess: function(info) {
				$('btn_submit').value = "Alterar";
				$('nome_utilizador').disabled = $('palavra_passe_antiga').disabled = $('palavra_passe_nova').disabled = $('palavra_passe_nova_confirmar').disabled = $('btn_submit').disabled = false;
				if($chk(info.tipo) && info.tipo == 'error') {
					utils.mostraErrorArray(eval(info.errorArray), 'alterar os dados');
				} else msgr.show({
					tipo: 'info',
					html: 'Os dados de acesso foram alterados'
				});
			}
		}).post($('form_dados_acesso'));

		// Espera
		$('btn_submit').value = "Aguarde...";
		$('nome_utilizador').disabled = $('palavra_passe_antiga').disabled = $('palavra_passe_nova').disabled = $('palavra_passe_nova_confirmar').disabled = $('btn_submit').disabled = true;

	},

	// ----------------------------------------------------------------------------------------------------
	sha1: function(msg) {
	// SHA-1 implementation in JavaScript (c) Chris Veness 2002-2009
	// http://www.movable-type.co.uk/scripts/sha1.html

		// function 'f' [§4.1.1]
		function f(s, x, y, z) {
			switch (s) {
				case 0: return (x & y) ^ (~x & z);			// Ch()
				case 1: return x ^ y ^ z;					// Parity()
				case 2: return (x & y) ^ (x & z) ^ (y & z);	// Maj()
				case 3: return x ^ y ^ z;					// Parity()
			}
		}
		// rotate left (circular left shift) value x
		// by n positions [§3.2.5]
		function ROTL(x, n) {
			return (x<<n) | (x>>>(32-n));
		}

		// constants [§4.2.1]
		var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];

		// Preprocessing
	 
		// add trailing '1' bit to string [§5.1.1]
		msg += String.fromCharCode(0x80);

		// convert string msg into 512-bit/16-integer
		// blocks arrays of ints [§5.2.1]

		// long enough to contain msg plus 2-word length
		var l = Math.ceil(msg.length/4) + 2;  
		// in N 16-int blocks
		var N = Math.ceil(l/16);			
		var M = new Array(N);
		for (var i=0; i<N; i++) {
			M[i] = new Array(16);
			// encode 4 chars per integer, big-endian encoding
			for (var j=0; j<16; j++) {  
				M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) |
							  (msg.charCodeAt(i*64+j*4+1)<<16) |
							  (msg.charCodeAt(i*64+j*4+2)<<8) |
							  (msg.charCodeAt(i*64+j*4+3));
			}
		}
		// add length (in bits) into final pair of 32-bit integers
		// (big-endian) [5.1.1]
		// note: most significant word would be
		// ((len-1)*8 >>> 32, but since JS converts
		// bitwise-op args to 32 bits, we need to simulate
		// this by arithmetic operators
		M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32);
		M[N-1][14] = Math.floor(M[N-1][14]);
		M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;

		// set initial hash value [§5.3.1]
		var H0 = 0x67452301;
		var H1 = 0xefcdab89;
		var H2 = 0x98badcfe;
		var H3 = 0x10325476;
		var H4 = 0xc3d2e1f0;

		// HASH COMPUTATION [§6.1.2]

		var W = new Array(80); var a, b, c, d, e;
		for (var i=0; i<N; i++) {

			// 1 - prepare message schedule 'W'
			for (var t=0;  t<16; t++)
				W[t] = M[i][t];
			for (var t=16; t<80; t++)
				W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);

			// 2 - initialise five working variables
			// a, b, c, d, e with previous hash value
			a = H0; b = H1; c = H2; d = H3; e = H4;

			// 3 - main loop
			for (var t=0; t<80; t++) {
				// seq for blocks of 'f' functions and 'K' constants
				var s = Math.floor(t/20);
				var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
				e = d;
				d = c;
				c = ROTL(b, 30);
				b = a;
				a = T;
			}

			// 4 - compute the new intermediate hash value
		   
			// note 'addition modulo 2^32'
			H0 = (H0+a) & 0xffffffff;  
			H1 = (H1+b) & 0xffffffff;
			H2 = (H2+c) & 0xffffffff;
			H3 = (H3+d) & 0xffffffff;
			H4 = (H4+e) & 0xffffffff;
		}

		return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();

	},

	// ----------------------------------------------------------------------------------------------------
	verificaAlterarSenha: function() {

		// Espera
		$('btn_alterar').value = "Espera...";
		var errorArray = new Array();

		// Senha actual
		var senhaActual = $('senha_actual').value;
		var senhaActualRequest = new Request.HTML(
			{
				url: 'modulos/seguranca/verificar_senha_actual.ajax.php',
				async: false,
				onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
					if(responseHTML.clean() != '1') this.errorArray.push('A senha actual est&aacute; errada');
				}
			}
		);
		senhaActualRequest.errorArray = errorArray;
		senhaActualRequest.get({senha_actual: senhaActual});

		// Senha nova
		var senhaNova = $('senha_nova').value;
		if(senhaNova.length < 4) errorArray.push('A senha nova &eacute; demasiado curta<br /><span class="nota">Escreve uma senha com 4 caracteres ou mais</span>');

		// Confirmacao
		var confirmacao = $('confirmacao').value;
		if(confirmacao != senhaNova) errorArray.push('A senha nova e a confirma&ccedil;&atilde;o n&atilde;o coincidem');

		// Se houver erros mostra-los, caso contrario enviar o formulario por AJAX
		if(errorArray.length) {
			utils.mostraErrorArray(errorArray, 'alterar a senha');
			$('btn_alterar').value = "Alterar";
		} else new Request.HTML(
			{
				url: 'modulos/seguranca/alterar_senha.ajax.php',
				onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
					msgr.show({
						tipo: 'info',
						html: 'A senha foi alterada.<br /><span class="nota">N&atilde;o te esque&ccedil;as de informar os outros administradores do site.</span>'
					});
					$('btn_alterar').value = "Alterar";
				}
			}
		).get({senha_nova: senhaNova});

	}

});
