$.extend($.v7r, {
	callbacks: {
		onSuccess: function () {
			// Esconde o form, procura pela janela mãe e pelo box de mensagem (filho direto da janela)
			this.hide().parents('.window:eq(0)').find('.form > div.msg')
				// Esvazia a mensagem, adiciona classe 'ok'
				.empty().addClass('ok')
				// Insere parágrafo com a mensagem de sucesso
				.append( $('<p>').text('Dados enviados com sucesso!') )
			;
		},
		onServerError: function () {
			this.find('div.msg').addClass('err').text('Ocorreu um erro no servidor, por favor tente mais tarde!');
		},
		onError: function () {
			this.find('div.msg').addClass('err').text('Foram encontrados erros nos dados. Por favor verifique e tente novamente.');
		}
	},
	apply_rules: function (elem, rules, callbacks) {
		
		// Atalho para o formulário
		var self = $(elem);
		
		var callbacks = $.extend({}, $.v7r.callbacks, callbacks);
		
		// Se não for um formulário, procura dentro do elemento
		if (!self.is('form')) {
			self = self.find('form');
		}
		
		self.bind('submit', function(e){
			
			// Evita que o form seja submetido
			e.preventDefault();
			
			// Valida o preenchimento
			if (!self.has_errors(rules)) {
				
				// Cancela se o form já estiver sendo submetido
				if (self.data('loading')) {
					return false;
				}
				
				// Marca o form como sendo submetido
				self.data('loading', true);
				self.find('div.msg').addClass('ok').text('Enviando, por favor aguarde...');
				
				// Envia o form por POST via ajax
				$.post(self.attr('action'), self.serialize(), function(data, textStatus){
					
					// Limpa marcação de "enviando"
					self.removeData('loading');
					self.find('div.msg').removeClass('ok');
					
					// Verifica se houve algum erro no servidor
					if (textStatus == 'error') {
						// Executa a função de erro
						callbacks.onServerError.call(self);
						return;
					}
					
					if (data == 'ok') {
						callbacks.onSuccess.call(self);
					}
					else {
						callbacks.onError.call(self);
					}
				}, 'text');
				
			}
			
		});
	}
});

$.extend($.v7r.options, {
	messages: {
		required: 'Campo obrigatório',
		is_email: 'Endereço de e-mail inválido',
		matches: 'Não confere',
		required_with: 'Campo obrigatório',
		is_date: 'Informe uma data no formato dd/mm/aaaa',
		is_number: 'Somente números',
		is_float: 'Informe um número válido',
		min_length: 'Número de caracteres inválido'
	},
	clear: function () {
		// Limpa classes de erro e o sumário de erros
		this.find('label.error').removeClass('error');
		this.find('div.msg').removeClass('error').empty();
	},
	error: function (errors) {
		
		var form = this;
		var error_list = $('<ul />');
		
		$.each(errors, function(){
			var field = form.find('[name=' + this.name + ']');
			var lb = field.parents('label:eq(0)').addClass('error');
			
			var span = lb.find('span:eq(0)');
			var field_label = (span.size() > 0) ? span.text() : lb.text();
			
			if (!field_label) {
				field_label = this.name.replace('_', ' ');
			}
			
			error_list.append(
				$('<li />')
					.append( $('<strong />').text(field_label + ': ') )
					.append( $.v7r.options.messages[this.rule] )
			);
		});
		
		form.find('label.error:eq(0) :input')[0].focus();
		
		var msg = form.find('div.msg').addClass('error');
		
		msg.append($('<p />').text('Foram encontrados erros no preenchimento:'));
		msg.append(error_list);
		
	}
});