/* Validacao de Formulario JavaScript (use Prototype 1.6.x ), version 0.1
 *--------------------------------------------------------------------------*/

/*
if (!Prototype) throw('Need prototype...'); else
if (parseFloat(Prototype.Version.substr(0,3)) < 1.6) throw('Wrong version of prototype...');
*/
var Validacao = Class.create();

/**
 * Mascara
 */
var Mascara = {
	telefone: function (value) {
		return value.replace(/\D/g,'').replace(/^(\d\d)(\d)/g,'($1) $2').replace(/(\d{4})(\d)/,'$1-$2');
	},
	cpf: function (value) {
		return value.replace(/\D/g,'').replace(/(\d{3})(\d)/,'$1.$2').replace(/(\d{3})(\d)/,'$1.$2').replace(/(\d{3})(\d{1,2})$/,'$1-$2');
	},
	cep: function (value) {
		return value.replace(/\D/g,'').replace(/^(\d{5})(\d)/,'$1-$2');
	},
	data: function (value) {
		return value.replace(/\D/g,'').replace(/^(\d\d{1})(\d)/,'$1/$2').replace(/(\d\d{1})(\d)/,'$1/$2');
	},
	numero: function(value) {
		return value.replace(/\D/g,'');
	},
	decimal: function(value) {
		return value.replace(/[^\d\,]/g,'');
	}
};

/**
 * Validacoes
 */
Object.extend(Validacao, {
	confirmacao: function(element) {
		var comparacao = element.name.replace('-confirmar', '')
		elementComparacao = this.form.getInputs(element.type, comparacao)[0];
		return elementComparacao.value == element.value && element.value != '';
	},

	checked: function(element) {
		return !!element.checked;
	},

	radio: function(element) {
		return !!element.checked;
	},
	
	cpf: function (element) {
		var cpf = element.value.replace(/[\.\-]/g,'');
		var invalidos = ['11111111111','22222222222','33333333333','44444444444','55555555555','66666666666','77777777777','88888888888','99999999999','00000000000'];
		
		if (!cpf || invalidos.include(cpf))
			return false;

		var i, digito = [], posicao = 10, soma = 0;
		var dv_informado = cpf.substr(9,2);

		for(i = 0; i <= 8; i++) {
			digito[i] = cpf.substr(i,1);
			soma = soma + digito[i] * posicao--;
		}

		digito[9] = soma % 11;

		if(digito[9] < 2)
			digito[9] = 0;
		else
			digito[9] = 11 - digito[9];

		posicao = 11;
		soma = 0;

		for (i = 0; i <= 9; i++)
			soma = soma + digito[i] * posicao--;
		
		digito[10] = soma % 11;

		if (digito[10] < 2)
			digito[10] = 0;
		else
			digito[10] = 11 - digito[10];

		dv = digito[9] * 10 + digito[10];

		if (dv == dv_informado)
			return true;
		else
			return false;
	}
});

Validacao.validacoes = {
	'texto': [/\w|\d/,'é um campo obrigatório'],
	'letra': [/\w/i,'precisa conter apenas letras'],
	'numero': [/\d/i,'precisa conter apenas números', 100, Mascara.numero],
	'decimal': [/\d|\.|\,/i,'precisa conter apenas números', 100, Mascara.decimal],
	'email': [/[A-Za-z0-9_.-]+@([A-Za-z0-9_]+\.)+[A-Za-z]{2,4}/i,'precisa conter um e-mail válido', 100],
	'data': [/(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/[12][0-9]{3}/i,'precisa conter uma data válida', 10, Mascara.data],
	'orkut': [/http:\/\/www\.orkut\.com\/Profile\.aspx\?uid\=[0-9]{10,}/i,'precisa ser válido', 50],
	'confirmacao': [Validacao.confirmacao,'deve ser preenchido corretamente'],
	'checked': [Validacao.checked,'precisa ser selecionado'],
	'radio': [Validacao.radio,'precisa ser selecionado'],
	'cpf': [Validacao.cpf,'precisa ser válido', 14, Mascara.cpf],
	'cep': [/\d{5}\-\d{3}/,'precisa ser válido', 9, Mascara.cep],
	'url': [/^(http[s]?:\/\/)?(www\.)?[a-zA-Z0-9-\.]+\.(com|org|net|mil|edu|ca|co.uk|com.au|gov|br|cc)[\/]?/,'precisa ser válido']
};

Object.extend(Validacao.prototype, {
	initialize: function(form) {
		this.form = $(form);

		if (!this.form)
			return false;

		form.getElements().each((function(element) {
			if (this.hasValidacao(element))
				this.setValidacao(element);
		}).bind(this));
	},
	
	hasValidacao: function(element) {
		return !element.className.blank() && this.getValidacao(element);
	},

	getValidacao: function(element) { 
		return element.className.match(/valida\[(\S{1,})\]/i);
	},

	setValidacao: function(element) {
		var classValidacao = this.getValidacao(element);
		var validation = classValidacao.last().split(',');

		element.valid = false;

		element.validation = validation[0];
		element.minlength = validation[1] || 0;
		element.edit = validation[3] === '1';
		element.maxlength = validation[4] || element.maxLength;

		if (element.maxlength && element.type == 'textarea')
			this.setMaxlength(element);
		else if (element.type == 'text' && element.maxLength === -1 && Validacao.validacoes[element.validation][2] > 0)
			element.maxLength = Validacao.validacoes[element.validation][2];
		
		element.className = element.className.replace(classValidacao.first(), '').strip();

		if (validation[2] == '1') 
			this.setMascara(element);

		if (!element.edit && !element.value.blank() && ['password','text','textarea'].include(element.type))
			this.setMensagem(element);

		if (['radio','checkbox'].include(element.type)) {
			if (Validacao.checked(element))
				element.valid = true;

			this.setCheckedValidation(element);
		}
	},
	
	setMascara: function(element) {
		var mascara;
		if(!(mascara = Mascara[element.validation] || Validacao.validacoes[element.validation][3]))
			return;

		var oldonkeypress = element.onkeypress;

		element.onkeypress = function() {
			setTimeout(function() {
				element.value = mascara(element.value);
			},1)
			
			if (oldonkeypress)
				oldonkeypress.bind(this)();
		}
	},
	
	setMensagem: function(element) {
		if (element.value && ['password','text','textarea'].include(element.type) && !element.edit) {
			element.maxLength = 100;
			element.value = element.defaultValue;
			
			element._onblur = element.onblur;

			element.onfocus = function() {
				if (this.value == this.defaultValue) {
					this.maxLength = element.maxlength;
					this.value = '';
				}
			}
			element.onblur = function() {
				if (this.value == '') {
					if (element._onblur) element._onblur();
					this.maxLength = 100;
					this.value = this.defaultValue;
				}
			}
		}
	},

	setMaxlength: function(element) {
		var maxlength = element.maxlength;
		var oldonkeydown = element.onkeydown;
		var oldonkeyup = element.onkeyup;

		var onMaxlength = function() {
			if (this.value.length > maxlength)
				this.value = this.value.substring(0, maxlength);
		};

		element.onkeydown = function() {
			onMaxlength.bind(this)();
			if (oldonkeydown)
				oldonkeydown.bind(this)();
		}

		element.onkeyup = function() {
			onMaxlength.bind(this)();
			if (oldonkeyup)
				oldonkeyup.bind(this)();
		}
	},
	
	setCheckedValidation: function(element) { 
		var validation;
		var oldonclick = element.onclick;

		if (Validacao.validacoes[element.validation][0].test)
			validation = Validacao.validacoes[element.validation][0].test;
		else
			validation = Validacao.validacoes[element.validation][0].bind(this);

		element.onclick = function() {
			
			element.valid = validation(element);
			if (oldonclick)
				oldonclick.bind(element)();
		}
	},

	verify: function() {
		var mensagem = 'Preencha corretamente o formulário:\n';
		var validado = true;
		var msg;

		this.refresh();

		this.form.getElements().each((function(element) {
			if (element.valid === true || !element.validation || (element.minlength == 0 && !['radio','checkbox'].include(element.type)))
				return;

			if (element.type == 'radio' && !!Form.serializeElements(this.form.getInputs('radio', element.name)))
				return;

			if (element.valid == 'empty' && element.validMessage)
				msg = element.validMessage;
			else if (element.valid == 'empty')
				msg = 'é um campo obrigatório';
			else if (element.valid == 'nominlength')
				msg = 'precisa ter no mínimo ' + element.minlength + ' caracteres.';
			else
				msg = Validacao.validacoes[element.validation][1];

			validado = false;
			mensagem += '\n- ' + element.title + ' ' + msg;
		}).bind(this));

		if (!validado)
			alert(mensagem);

		return validado;
	},

	clear: function() {
		this.form.getElements().each((function(element) {
			if (element.validation && !Validacao.checked(element))
				element.valid = false;
		}).bind(this));
	},

	refresh: function() {
		this.form.getElements().each((function(element) {
			if (element.validation) {
				if (['radio','checkbox'].include(element.type)) {
					if (Validacao.checked(element))
						element.valid = true;
					else
						element.valid = false;
				} else if ((element.value.length == 0 && parseInt(element.minlength) == 1) || (element.value == element.defaultValue && !element.edit && element.type != 'hidden'))
					element.valid = 'empty';
				else if (element.value.length < parseInt(element.minlength))
					element.valid = 'nominlength';
				else if (Validacao.validacoes[element.validation][0].test)
					element.valid = Validacao.validacoes[element.validation][0].test(element.value);
				else if (Validacao.validacoes[element.validation][0])
					element.valid = Validacao.validacoes[element.validation][0].bind(this)(element);
				else
					element.valid = false;
			}
		}).bind(this));
	},
	
	submit: function() {
		if (this.verificaValidacoes())
			this.form.submit();
	}
});

Validacao.start = function() {
	$$('form').each(function(form) {
		var oldSubmit = form.onsubmit;
		form.validador = new Validacao(form);

		form.onsubmit = function() {
			try {
				if (this.validador.verify()) {
					this.validador.clear();

					if (!oldSubmit)
						return true;
					else
						return !!oldSubmit.bind(this)();
				} 
				
				return false;
			} catch (e) {
				alert('Erro:'+e.message+'\nArquivo:'+e.fileName+'\nLinha:'+e.lineNumber);
				return false;
			}

		};
	});
};

Validacao.start();
