/* Form Validation*/
(function(jQuery){
	var defaultOptions = {
			parent: '',
			errorClass: 'erro',
			thousands:'.',
			decimal:','
	};
		
	var validations = {
		isValid: function(value, validation, options){
			var options = $.extend(defaultOptions, options);
			var valid = true;
			this.message = '';
			var validation = this[validation];
			if(!validation){
				return true;
			}
			if(validation.re && !validation.re.test(value)){
				valid = false;
			}
			if(validation.callback && !validation.callback(value, options)){
				valid = false;
			}
			if(!valid){
				this.message = validation.message;
			}
			return valid;
		},
		
		required: {
			re: /.+/,
			message: 'Este campo é obrigatório'
		},
		cep: {
			mask: '99999-999',
			re: /^(\d{5}-\d{3})?$/,
			message: 'CEP inválido'
		},
		email: {
			callback: function(value){
				return value == '' || value.isEmail();
			},
			message: 'E-mail inválido'
		},
		ddd: {
			mask: '99',
			re:/^(\d{2})?$/,
			message: 'DDD inválido'
		},
		telefone: {
			mask: '9999-9999',
			re:/^(\d{4}\D*\d{4})?$/,
			message: 'Telefone inválido'
		},
		cpf: {
			mask: '999.999.999-99',
			callback: function(value){
				return value == '' || value.isCPF();
			},
			message: 'CPF inválido'
		},
		cnpj: {
			mask: '99.999.999/9999-99',
			callback: function(value){
				return value == '' || value.isCNPJ();
			},
			message: 'CNPJ inválido'
		},
		rg: {
			mask: '99.999.999-*',
			re: /^(\d{2}\.\d{3}\.\d{3}-.)?$/,
			message: 'RG inválido'
		},
		'date': {
			mask: '99/99/9999',
			re: /^(\d{2}\/\d{2}\/\d{4})?$/,
			callback: function(value){
				return value == '' || isDate(value, /^(\d{2})\/(\d{2})\/(\d{4})$/, {d: 1, m:2, y:3}) == 0;
			},
			message: 'Data inválida'
		},
		ano: {
			mask: '9999',
			re: /^(\d{4})?$/,
			message: 'Ano inválido'
		},
		placa: {
			mask: 'ccc 9999',
			re: /^([A-Z]{3}\s\d{4})?$/,
			message: 'Placa inválida'
		},
		money: {
			mask: 'M',
			callback: function(value, options){
				while(value.indexOf(options.thousands) != -1){
					value = value.replace(options.thousands, '');
				}
				value = value.replace(options.decimal, '.');
				return value == '' || isFinite(value);
			},
			message: 'Valor inválido'
		},
		'inscricao-estadual': {
			mask: '999.999.999.999', 
			re: /^(\d{3}\.\d{3}\.\d{3}\.\d{3})?$/,
			message: 'Inscrição estadual inválida'
		},
		integer: {
			mask: 'N',
			callback: function(value, options){
				while(value.indexOf(options.thousands) != -1){
					value = value.replace(options.thousands, '');
				}
				value = value.replace(options.decimal, '.');
				return value == '' || isFinite(value);
			},
			message: 'Número inválido'
		},
		url: {
			re: /^((([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?)?$/,
			message: 'Site inválido'
		},
		time: {
			mask: '99:99',
			re: /(\d{2}:\d{2})?/,
			message: 'Horário inválido'
		},
		datetime: {
			mask: '99/99/9999 99:99',
			re: /^(\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2})?$/,
			callback: function(value){
				return value == '' || isDate(value, /^(\d{2})\/(\d{2})\/(\d{4}\s\d{2}:\d{2})$/, {d: 1, m:2, y:3}) == 0;
			},
			message: 'Data inválida'
		},
		confirma: {
			callback: function(value, options){
				var name = options.element.name + '_confirma';
				var confirma = $('[@name=' + name + ']').val();
				return value == confirma;
			},
			message: 'Campos não coincidem'
		},
		jpg: {
			re: /(^$|jpg$)/i,
			message: 'Arquivo inválido'
		}
	}

	jQuery.fn.message = function(message, options){
		var options = $.extend(defaultOptions, options);
		this.each(function(){
			$(this).addClass(options.errorClass).parents(options.parent).eq(0).addClass(options.errorClass);
			$(this).parent().append('<div class="' + options.errorClass + '">' + message + '</div>');
		});
		return this;
	}

	jQuery.fn.validate = function(validation, options)
	{
		if(typeof validation == 'function'){
			return this.bind('validate', validation);
		}else if(arguments.length == 0){
			return this.trigger('validate');
		}else if(typeof validation == 'object'){
			var options = validation;
		}else if(typeof validation == 'string'){
			var options = {parent: validation};
		}
		
		var options = $.extend(defaultOptions, options);
		
		function inputValidate(){
			$(this).parents(options.parent).eq(0).removeClass(options.errorClass).find('div.' + options.errorClass).remove()
			.end().find('.' + options.errorClass).removeClass(options.errorClass);
			if($(this).attr('disabled')){
				return true;
			}
			var value = $(this).val().trim();
			var valid = true;
			var classes = this.className.split(' ');
			var element = this;
			$.each(classes, function(){
				if(typeof validations[this] == 'object' && !validations.isValid(value, this, {'element': element})){
					$(element).message(validations.message, options);
					valid = false;
				}
			});
			return valid;
		}
		
		function formValidate(){
			$(this).find('div.' + options.errorClass).remove();
			$(this).find('.' + options.errorClass).removeClass(options.errorClass);
			$.each(this.elements, function(){
				$(this).validate();
			});
		}

		this.each(function(){
			$.each(this.elements, function(){
				var element = this;
				if(/text|password|file/i.test(this.type) || /textarea|select/i.test(this.nodeName)){
					var classes = this.className.split(' ');
					$.each(classes, function(){
						if(typeof validations[this] == 'object' && typeof validations[this].mask == 'string'){
							$(element).mask(validations[this].mask, options);
						}
					});
//					$(element).unbind('validate', inputValidate);
					$(element).validate(inputValidate).blur(function(){
						$(element).validate();
					});
				}
			});

			$(this).validate(formValidate).submit(function(e){
				$(this).validate();
				if($(this).find('.erro').size() > 0){
					var element = false;
					$.each(this.elements, function(){
						if(jQuery.className.has(this, options.errorClass) && !element){
							element = true;
							this.focus();
							return false;
						}
					});
					e.preventDefault();
				}else{
					$.each(this.elements, function(){
						$(this).submit();
					});
				}
			});
//			this.elements[0].focus();
		});
		return this;
	}
})(jQuery);