/*
Validador de formulário 1.0 Beta

Licença:
	[CC3.0] http://creativecommons.org/licenses/by-nc-sa/3.0/

Copyright:
	Copyright (c) 2008 [Igor Frias Vieira](http://igorvieira.com/).

Documentação:
	//Ta em construção
	(http://igorvieira.com/projects/form_validator/).

Inspiração:
	RubyOnRails [www.rubyonrails.org]


Outros:
	Este validador usa MooTools 1.2 [http://mootools.net/]
	MooTools Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/).

Você precisa:
	Mootools 1.2 core:
		Native...
		Class...
		Lorem Ipsum...

	Mootools 1.2 more: (plugins)
		Slide...
		Fx...
		Css...
		Lorem Ipsum...

Obrigado para:
	Ricardo José - meu testador...(e ele também prometeu que iria converter meu codigo para jQuery assim que estiver pronto)

*/



//Inicializa a classe recebendo o form_id
//Será preciso uma instancia da classe para cada formulário na página
var FormValid = new Class({

    initialize: function(form_id){

		if($defined(form_id))
		{
		//if the user will use an form
			if($(form_id))
			{
			//Se o ID existir

				form_obj = $(form_id);

				//Checando se é um formulário
				if(!form_obj.match('form'))
				{
					alert('Este ID não é de um formulário!');
				}
				else
				{
					this.form_obj = form_obj;
				}
			}
			else
			{
				alert('Erro - Por favor, passe um ID válido!');
				this.form_obj = null;
			}
		}
		else
		{
			alert('Erro - Você precisa passar o ID de um formulário!');
			this.form_obj = null;
		}

		//Iniciando algumas variaveis
		this.inputs = new Array();
		this.p_mode = "modal";

		this.mess_error1 = "Foi encontrado <_NUM_> erro:";
		this.mess_error2 = "Foram encontrados <_NUM_> erros:";


		this.input_color = ["#FFFFFF", "#FFCCCC"];

		if(!$('my_wmodal_id'))
		{
			//Criando a janela modal
			this.modal_window = new Element('div', {
				styles: {
					'opacity': 0,
					'position': 'absolute'
				},
				'class': 'my_wmodal_class',
				'id': 'my_wmodal_id'
			});

				this.modal_back = new Element('div', {
					styles: {
						'opacity': 0,
						'position': 'absolute'
					},

					'class': 'my_back_wmodal_class',
					'id': 'my_back_wmodal_id'
				});



			this.modal_back.injectInside(document.body);
			this.modal_window.injectInside(document.body);
		}

    },


	//Adiciona um novo campo para ser validado
    add: function(input_id, type_of_validation, value, error_message, required)
	{
		//Um array com as opições para validação
        var valid_array = [$(input_id), type_of_validation, value, error_message, required];

		this.inputs.include(valid_array);
    },


	//Função que validará os campos
	validate: function()
	{
		this.error = new Array();
		var setFocusIn = true;

		for(var cont=0; this.inputs.length > cont; cont++)
		{
			input = this.inputs[cont];
			var input_obj = input[0];
			var validation = input[1];
			var validation_value = input[2];
			var message = input[3];
			var required = input[4];

			var valid = null;
            input_obj = document.getElementById(input_obj.name);

			if ((required)
			||	((!required)
			&&	 (input_obj.value != ""))) {
				switch(validation)
				{
					case "email": 	valid = this.val_email(input_obj);
									break;

					case "minimum": valid = this.val_minimum(input_obj, validation_value);
									break;

					case "maximum": valid = this.val_maximum(input_obj, validation_value);
									break;

					case "within": valid = this.val_within(input_obj, validation_value);
									break;

					case "exact": valid = this.val_exact(input_obj, validation_value);
									break;

					case "presence": valid = this.val_presence(input_obj);
									break;

					case "ereg": valid = this.val_ereg(input_obj, validation_value);
									break;

					case "alpha": valid = this.val_alpha(input_obj);
									break;

					case "num": valid = this.val_num(input_obj);
									break;

					case "alphanum": valid = this.val_alphanum(input_obj);
									break;

					case "accept": valid = this.val_accept(input_obj);
									break;

					case "inclusion": valid = this.val_inclusion(input_obj, validation_value);
									break;

					case "confirmation": valid = this.val_confirmation(input_obj);
									break;

					case "cpf": valid = this.val_cpf(input_obj);
									break;

					case "cnpj": valid = this.val_cnpj(input_obj);
									break;

					case "range": valid = this.val_range(input_obj, validation_value);
									break;
					case "moeda": valid = this.val_moeda(input_obj, validation_value);
                                  break;

				}
			}

			//Se a variavel valid for null significa que não foi passada uma opição válida
			if(valid != null)
			{
				if(!valid[0])
				{
					if(message != null)
					{
						this.error.include(message);
					}
					else
					{
						this.error.include(valid[1]);
					}

					//Colocando o focus no primeiro campo com erro
					if(setFocusIn)
					{
						input_obj.focus();
						setFocusIn = false;
					}

					input_obj.tween('background-color', this.input_color[1]);

					if(validation == 'confirmation')
					{
						$(input_obj.id + "_confirmation").tween('background-color', this.input_color[1]);
					}

				}
				else
				{

					input_obj.tween('background-color', this.input_color[0]);

					if(validation == 'confirmation')
					{
						$(input_obj.id + "_confirmation").tween('background-color', this.input_color[0]);
					}

				}
			}


		}


		if(this.error.length > 0)
		{
			this.print_error();
			return false;
		}else{
			return true;
		}

	},


	send: function()
	{
		return this.validate();
	},







/*
	As funções que realmente fazer a validação ;D
*/
	//Validando o e-mail
	val_email: function(obj)
	{
		if($defined(obj))
		{
			if(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,3})+$/.test(obj.value))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " precisa ser um e-mail."];
			}
		}

		return null;
	},

	//Validando o cpf
	val_cpf: function(obj)
	{
		if(($defined(obj)) && (!document.getElementById(obj.name).disabled))
		{
                //alert(document.getElementById(obj.name).disabled);
                var CPF = obj.value; // Recebe o valor digitado no campo
                erro = new String;
                CPF=CPF.replace(".", "");
                CPF=CPF.replace(".", "");
                CPF=CPF.replace("-", "");
                // Aqui começa a checagem do CPF
                var POSICAO, I, SOMA, DV, DV_INFORMADO;
                var DIGITO = new Array(10);
                DV_INFORMADO = CPF.substr(9, 2); // Retira os dois últimos dígitos do número informado

                // Desemembra o número do CPF na array DIGITO
                for (I=0; I<=8; I++) {
                  DIGITO[I] = CPF.substr( I, 1);
                }

                // Calcula o valor do 10º dígito da verificação
                POSICAO = 10;
                SOMA = 0;
                for (I=0; I<=8; I++) {
                   SOMA = SOMA + DIGITO[I] * POSICAO;
                   POSICAO = POSICAO - 1;
                }

                DIGITO[9] = SOMA % 11;
                if (DIGITO[9] < 2) {
                    DIGITO[9] = 0;
                }else{
                    DIGITO[9] = 11 - DIGITO[9];
                }

                // Calcula o valor do 11º dígito da verificação
                POSICAO = 11;
                SOMA = 0;
                for (I=0; I<=9; I++) {
                   SOMA = SOMA + DIGITO[I] * POSICAO;
                   POSICAO = POSICAO - 1;
                }
                DIGITO[10] = SOMA % 11;
                if (DIGITO[10] < 2) {
                   DIGITO[10] = 0;
                }else{
                   DIGITO[10] = 11 - DIGITO[10];
                }

                // Verifica se os valores dos dígitos verificadores conferem
                DV = DIGITO[9] * 10 + DIGITO[10];
                if (DV != DV_INFORMADO) {
                   erro +="CPF inválido!";
                   return [false, erro];
                }

                return [true];
		}

		return null;
	},

	//Validando o cnpj
	val_cnpj: function(obj)
	{
		if(($defined(obj)) && (!document.getElementById(obj.name).disabled))
		{
                CNPJ = obj.value;
				erro = new String;
                CNPJ=CNPJ.replace(".", "");
                CNPJ=CNPJ.replace(".", "");
                CNPJ=CNPJ.replace("/", "");
                CNPJ=CNPJ.replace("-", "");
				var nonNumbers = /\D/;

				var a = [];
				var b = new Number;
				var c = [6,5,4,3,2,9,8,7,6,5,4,3,2];
				for (i=0; i<12; i++){
					a[i] = CNPJ.charAt(i);
					b += a[i] * c[i+1];
				}
				if ((x = b % 11) < 2) { a[12] = 0 } else { a[12] = 11-x }
				b = 0;
				for (y=0; y<13; y++) {
					b += (a[y] * c[y]);
				}
				if ((x = b % 11) < 2) { a[13] = 0; } else { a[13] = 11-x; }
				if ((CNPJ.charAt(12) != a[12]) || (CNPJ.charAt(13) != a[13])){
					erro +="Digito verificador do CNPJ com problema!";
				}
				if (erro.length > 0){
					return [false, erro];
				} else {
					return [true];
				}
		}

		return null;
	},

	//Validando o valor minimo
	val_minimum: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			validation_value = validation_value.toInt();

			if(obj.value.length >= validation_value)
			{
				return [true];
			}
			else
			{
				var qtd_caracter = " caracters."

				if(validation_value == 1)
					qtd_caracter = " caracter."

				return [false, obj.name + " precisa conter no mínimo " + validation_value + qtd_caracter];
			}
		}

		return null;
	},





	//Validando o valor maximo
	val_maximum: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			validation_value = validation_value.toInt();

			if(obj.value.length <= validation_value)
			{
				return [true];
			}
			else
			{
				var qtd_caracter = " caracters."

				if(validation_value == 1)
					qtd_caracter = " caracter."

				return [false, obj.name + " precisa conter no máximo " + validation_value + qtd_caracter];
			}
		}

		return null;
	},





	//Validando uma quantidade entre 2 valores
	val_within: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			validation_value = validation_value.split("..");

			if(obj.value.length >= validation_value[0].toInt() && obj.value.length <= validation_value[1].toInt())
			{
				return [true];
			}
			else
			{
				var qtd_caracter = " caracters."

				if(validation_value == 1)
					qtd_caracter = " caracter."

				return [false, obj.name + " precisa conter no mínimo " + validation_value[0] + " e no máximo " + validation_value[1] + qtd_caracter];
			}
		}

		return null;
	},



	//Validando um valor entre 2 valores
	val_range: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			validation_value = validation_value.split("..");

			if(obj.value >= validation_value[0].toInt() && obj.value <= validation_value[1].toInt())
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " precisa estar entre " + validation_value[0] + " e no máximo " + validation_value[1]];
			}
		}

		return null;
	},



	//Validando um valor monetário
	val_moeda: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			switch (validation_value){
            case "BRA":
                        reMoeda = /^\d{1,3}(\.\d{3})*\,\d{2}$/;
                        if (obj.value != "" && reMoeda.test(obj.value)) {
                            return [true];
                        } else {
                            return [false, obj.name + "Valor monetário incorreto"];
                        }
                        break;
            }
		}

		return null;
	},


	//Validando valor com exatamente X caracters
	val_exact: function(obj, validation_value)
	{
		if($defined(obj) && $defined(validation_value))
		{
			validation_value = validation_value.toInt();

			if(obj.value.length == validation_value)
			{
				return [true];
			}
			else
			{
				var qtd_caracter = " caracters."

				if(validation_value == 1)
					qtd_caracter = " caracter."

				return [false, obj.name + " precisa conter exatamente " + validation_value + qtd_caracter];
			}
		}

		return null;
	},






	//Validando valor com exatamente X caracters
	val_presence: function(obj)
	{
		if(($defined(obj)) && (!document.getElementById(obj.name).disabled))
		{

			if($chk(obj.value))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " precisa ser preenchido."];
			}
		}

		return null;
	},







	//Validando expressao regular ersonalizada
	val_ereg: function(obj, regexp)
	{
		if($defined(obj) && $defined(regexp))
		{

			if(obj.value.match(regexp))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " é inválido."];
			}
		}

		return null;
	},







	//Validando se o campo possuí apenas caracters e espaço em branco
	val_alpha: function(obj)
	{
		if($defined(obj))
		{

			if(obj.value.match("^[a-zA-ZÀ-ü ]*$"))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " não é uma letra."];
			}
		}

		return null;
	},





	//Validando se o campo possuí apenas numeros e espaço em branco
	val_num: function(obj)
	{
		if($defined(obj))
		{

			if(obj.value.match("^[0-9 ]*$"))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " não é um número."];
			}
		}

		return null;
	},





	//Validando se o campo possuí apenas números, caracters e espaços em branco
	val_alphanum: function(obj)
	{
		if($defined(obj))
		{

			if(obj.value.match("^[a-zA-ZÀ-ü0-9 ]*$"))
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " não é uma letra e nem um número"];
			}
		}

		return null;
	},





	//Validando se o checkbox foi selecionado
	val_accept: function(obj)
	{
		if($defined(obj))
		{

			if(obj.checked == true)
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " precisa ser selecionado"];
			}
		}

		return null;
	},






	//Validando se o item está na lista
	val_inclusion: function(obj, list)
	{
		if($defined(obj))
		{

			if(list.indexOf(obj.value) != -1)
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " ser um item da lista."];
			}
		}

		return null;
	},





	//Validando confirmação de campo
	val_confirmation: function(obj)
	{
		if($defined(obj))
		{

			if(obj.value == $(obj.id + "_confirmation").value)
			{
				return [true];
			}
			else
			{
				return [false, obj.name + " não foi repetido corretamente"];
			}
		}

		return null;
	},






/*
	A mágica, as mensagens de erro e o MooTools FX =D
*/

	print_error: function()
	{
		if(this.p_mode == "alert")
		{
			var br = "\n";
		}
		else
		{
			var br = "<br />";
		}

		this.error_string = "";
		for(var cont=0; this.error.length > cont; cont++)
		{
			erro = this.error[cont];

			this.error_string += br + " • " + erro;
		};

		var total_errors = this.error.length;

		if(total_errors == 1)
		{
			mess_error = this.mess_error1.replace("<_NUM_>",total_errors);
		}
		else
		{
			mess_error = this.mess_error2.replace("<_NUM_>",total_errors);
		}


			if(this.p_mode == "alert")
			{
				alert(mess_error + br + this.error_string);
			}
			else if(this.p_mode == "modal")
			{
				this.open_modal("<strong>" + mess_error + "</strong>" + br + this.error_string);
			}
			else if(this.p_mode == "div")
			{
				$(this.div_id).innerHTML = "<strong>" + mess_error + "</strong>" + br + this.error_string;
			}

	},




	open_modal: function(error_text)
	{

	closing = function(){
					$('my_wmodal_id').tween('opacity', 0);
					$('my_back_wmodal_id').tween('opacity', 0);
					$clear(anin_modal);

					$('my_back_wmodal_id').removeEvent('click', closing);

				}

		anin_modal = setInterval(function(){

			var w_width = $('my_wmodal_id').getWidth();
			var w_height = $('my_wmodal_id').getHeight();

			$('my_wmodal_id').style.marginLeft = ((w_width/2) * -1) + window.getScrollLeft() + "px";
			$('my_wmodal_id').style.marginTop = ((w_height/2) * -1) + window.getScrollTop() + "px";

			$('my_wmodal_id').style.top = "50%";
			$('my_wmodal_id').style.left = "50%";

		}, 25);

		$('my_back_wmodal_id').style.height = window.getScrollHeight() + "px";


		$('my_wmodal_id').innerHTML = "<span>" + error_text + "</span>";

		var w_width = $('my_wmodal_id').getWidth();
		var w_height = $$('#my_wmodal_id span').getHeight();


		$('my_wmodal_id').style.width = "50px";
		$('my_wmodal_id').style.height = "50px";

		$$('#my_wmodal_id span').tween('opacity', 0, 0);
		$('my_back_wmodal_id').tween('opacity', .8);
		$('my_wmodal_id').tween('opacity', 1);

		setTimeout(function(){

			$('my_wmodal_id').tween('height', w_height);

		}, 500);

		setTimeout(function(){

			$('my_wmodal_id').tween('width', w_width);

		}, 1000);

		setTimeout(function(){

			$$('#my_wmodal_id span').tween('opacity', 1);

				$('my_back_wmodal_id').addEvent('click', closing);

		}, 1500);

	},







	//Mensagem de erro personalizada
	set_error_mess: function(mess_error1, mess_error2)
	{
		if($defined(mess_error1) && $defined(mess_error1))
		{
			if(mess_error1 != "")
			{
				this.mess_error1 = mess_error1;
			}

			if(mess_error2 != "")
			{
				this.mess_error2 = mess_error2;
			}
		}
	},




	//Seleciona a maneira como a mensagem será exibida (alert, modal ou div)
	print_mode: function(p_mode, div_id)
	{
		this.div_id = false;


		if(p_mode == "alert" || p_mode == "modal")
		{
			this.p_mode = p_mode;
		}

		if(p_mode == "div" && $defined(div_id))
		{
			this.p_mode = p_mode;
			this.div_id = div_id;

		}
	},




	//Seleciona a cor de fundo do input em caso de erro
	input_bg: function(old_bg_color, bg_color)
	{
		if(old_bg_color.match("^[#0-9a-fA-F]{7}$") && bg_color.match("^[#0-9a-fA-F]{7}$"))
		{
			this.input_color = [old_bg_color, bg_color];
		}
	}

});

var anin_modal;
var closing;