//----------------------------------------------------------------------------------
// File: validationaide.js 
//
// Copyright (c) 2007 Ste Brennan (dnaide.com)
// Licensed under the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
// http://www.opensource.org/licenses/cddl1.php
//
//----------------------------------------------------------------------------------

//
// Validator Rule classes
//
function ValidatorRule (name, errorMessage, validationMethod){
	this.validationMethod = validationMethod;
	this.errorMessage = errorMessage ? errorMessage : 'Validation failed.';
	this.name = name;
};
ValidatorRule.prototype = {
	doValidation : function(fieldValue, fieldObj) {
		return this.validationMethod(fieldValue, fieldObj);
	}
};

//
// Validator Rule Collection class
//
function ValidatorRuleCollection(){
	this.items = {};
};
ValidatorRuleCollection.prototype = {
	add : function(name, errorMessage, testFunction) {
		this.items[name] = new ValidatorRule(name, errorMessage, testFunction);
	}
};

//
// Static methods
//
jQuery.validationAide = {
	getDefaultValidationRules : function(){
	
		var rules = new ValidatorRuleCollection();
		
		rules.add('valida-cpf', 'CPF Inválido', function(fieldValue, fieldObj) {

		   erro = new String;
		 
			if (fieldValue.length == 11)
			{	
					fieldValue = fieldValue.replace('.', '');
					fieldValue = fieldValue.replace('.', '');
					fieldValue = fieldValue.replace('-', '');
		 
					var nonNumbers = /\D/;
			
					if (nonNumbers.test(fieldValue)) 
					{
							erro = "A verificacao de CPF suporta apenas números!"; 
					}
					else
					{
							if (fieldValue == "00000000000" || 
									fieldValue == "11111111111" || 
									fieldValue == "22222222222" || 
									fieldValue == "33333333333" || 
									fieldValue == "44444444444" || 
									fieldValue == "55555555555" || 
									fieldValue == "66666666666" || 
									fieldValue == "77777777777" || 
									fieldValue == "88888888888" || 
									fieldValue == "99999999999") {
									
									erro = "Número de CPF inválido!"
							}
			
							var a = [];
							var b = new Number;
							var c = 11;
		 
							for (i=0; i<11; i++){
									a[i] = fieldValue.charAt(i);
									if (i < 9) b += (a[i] * --c);
							}
			
							if ((x = b % 11) < 2) { a[9] = 0 } else { a[9] = 11-x }
							b = 0;
							c = 11;
			
							for (y=0; y<10; y++) b += (a[y] * c--); 
			
							if ((x = b % 11) < 2) { a[10] = 0; } else { a[10] = 11-x; }
			
							if ((fieldValue.charAt(9) != a[9]) || (fieldValue.charAt(10) != a[10])) {
								erro = "Número de CPF inválido.";
							}
					}
			}
			else
			{
				if(fieldValue.length == 0)
					return false
				else
					erro = "Número de CPF inválido.";
			}
			if (erro.length > 0) {
					//alert(erro);
					return false;
			} 	
			return true;	
	    });
		
		rules.add('valida-campo', 'Preencha o campo', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return false;
			return true;
		});
		rules.add('valida-diames', 'Preencha o campo', function(fieldValue, fieldObj) {
			if (fieldValue == "" || fieldValue.length < 2)	return false;
			return true;
		});
		rules.add('valida-ano', 'Ano inválido', function(fieldValue, fieldObj) {
			if (fieldValue == "" || fieldValue.length < 4 || fieldValue < 1900)	return false;
			return true;
		});
		rules.add('valida-cep', 'Dado inválido', function(fieldValue, fieldObj) {
			if (fieldValue == "" || fieldValue.length < 8)	return false;
			return true;
		});
		
		rules.add('valida-email', 'Endereço de e-mail inválido', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			return /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(fieldValue);
		});
		
		rules.add('valida-numero', 'Número inválido', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			return (!isNaN(fieldValue) && !/^\s+$/.test(fieldValue));
		});
		
		rules.add('valida-digito', 'Apenas digitos são permitidos', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			return !/[^\d]/.test(fieldValue);
		});
		
		rules.add('valida-alfanumerico', 'Apenas letras(a-z) ou numeros (0-9) permitidos', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			return !/\W/.test(fieldValue);
		});
		
		rules.add('valida-data-ddmmyyyy', 'Data inválida, precisa ser dd/mm/aaaa', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
			if(!regex.test(fieldValue)) return false;
			var d = new Date(v.replace(regex, '$2/$1/$3'));
			return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) && 
							(parseInt(RegExp.$1, 10) == d.getDate()) && 
							(parseInt(RegExp.$3, 10) == d.getFullYear() );
		});
		
		rules.add('valida-data-mmddyyyy', 'Data inválida, precisa ser mm/dd/aaaa', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
			if(!regex.test(fieldValue)) return false;
			var d = new Date(fieldValue.replace(regex, '$2/$1/$3'));
			return ( parseInt(RegExp.$1, 10) == (1+d.getMonth()) ) && 
							(parseInt(RegExp.$2, 10) == d.getDate()) && 
							(parseInt(RegExp.$3, 10) == d.getFullYear() );
		});
		
		rules.add('valida-url', 'URL inválida.', function(fieldValue, fieldObj) {
			if (fieldValue == "")	return true;
			return /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(fieldValue);
		});

		return rules;
	},
	
	
	extendOptions : function(options){
	
		var retval = jQuery.extend({}, options || {});
		
		if (typeof retval.showInlineMessages == 'undefined')
			retval.showInlineMessages = false;
		
		if (typeof retval.inlineShowSpeed == 'undefined')
			retval.inlineShowSpeed= "";
			
		if (typeof retval.inlineMessageElementIdPrefix == 'undefined')
			retval.inlineMessageElementIdPrefix= "ValidationInlineErrorMessage-";
		
		if (typeof retval.inlineMessageCssClass == 'undefined')
			retval.inlineMessageCssClass= "validation-inline-error-message";
		
		if (typeof retval.showSummary == 'undefined')
			retval.showSummary = true;
			
		if (typeof retval.summaryElementId == 'undefined')
			retval.summaryElementId = "ClientValidationSummary";
		
		if (typeof retval.summaryMessage == 'undefined')
			retval.summaryMessage = "Por favor corrija os seguintes campos:";
			
		if (typeof retval.summaryFieldMessageFormat == 'undefined')
			retval.summaryFieldMessageFormat = "##FIELD## - ##MESSAGE##";
			
		if (typeof retval.fieldErrorCssClass == 'undefined')
			retval.fieldErrorCssClass = "validation-failed";
	
		return retval;
	},
	
	
	resetForm : function (formId, options){
	
		if (typeof jQuery.fn.fieldStringVal != "function"){
			alert("Warning, validation will not work unless stringaide is loaded!");
		}
	
		var fullOptions = jQuery.validationAide.extendOptions(options);
		
		if (fullOptions.showSummary){
			// Hide summary container
			jQuery("#" + fullOptions.summaryElementId).html("").hide();
		}
			
		// Loop through each input and remove any previous inline error message / classes
		jQuery(formId + " :input").each( function(){
			var inlineMessageElementId = "#" + fullOptions.inlineMessageElementIdPrefix + this.id;
			jQuery(inlineMessageElementId).remove();
			jQuery(this).removeClass(fullOptions.fieldErrorCssClass);
		});
	
	},
	
	
	validateForm : function(formId, validationRules, options, preFieldValidation, postFieldValidation){
		jQuery.validationAide.resetForm(formId, options);
		
		var fullOptions = jQuery.validationAide.extendOptions(options);
				
		var validatedOK = true;
		
		validationRules = validationRules ? validationRules : jQuery.validationAide.getDefaultValidationRules();
	
	  var scrollTo = "";
	  var focusField = "";
	  var firstErroredField = true;
	  
	  if (fullOptions.showSummary){
			var messagesForSummary = new Array();
			var fieldsForSummary = new Array();
	  }
	  
		// Loop through each input and validate
		jQuery(formId + " :input").each( function(){
			
			var elmId = this.id;
			
			if (elmId != ""){
				var jQueryElm = jQuery(this);
				var cssClassesStr = new String(jQueryElm.attr("class")); 
				cssClassesStr = jQuery.trim(cssClassesStr);
				if (cssClassesStr.length > 0){
					var cssClasses = cssClassesStr.split(" ");
									
					for (var i=0; i<cssClasses.length; i++){
						
						var validationRule = validationRules.items[cssClasses[i]];					
						
						if (validationRule){
							
							// Get value of the field as a string
							var fieldValue = jQueryElm.fieldStringVal();
							
							// Fire off preFieldValidation event
							if (typeof preFieldValidation == 'function')
								preFieldValidation(fieldValue, this);
							
							var retval = validationRule.doValidation(fieldValue, this);
							
							// Fire off postFieldValidation event
							if (typeof postFieldValidation == 'function')
								postFieldValidation(fieldValue, this, retval);
							
							if (!retval){
							
								validatedOK = false;
								
								// Set focus and scroll to the first errored element
								if (firstErroredField){
									scrollTo = elmId;
									focusField = elmId;
									firstErroredField = false;
								}
								
								// Set the error css class
								jQueryElm.addClass(fullOptions.fieldErrorCssClass);
								
								var fieldFriendlyName = jQueryElm.attr("title");	
								if (!fieldFriendlyName || fieldFriendlyName == 'undefined')
									fieldFriendlyName = elmId;
								
								if (fullOptions.showSummary){
									// Add the message to the summary array
									fieldsForSummary.push(elmId);
									var messageForSummary = new String(fullOptions.summaryFieldMessageFormat);
									messageForSummary = messageForSummary.replace("##FIELD##", fieldFriendlyName);
									messageForSummary = messageForSummary.replace("##MESSAGE##", validationRule.errorMessage);
									messagesForSummary.push(messageForSummary);
								}
											
								if (fullOptions.showInlineMessages){
									var inlineMessageElementId = fullOptions.inlineMessageElementIdPrefix + elmId;
									// Insert the inline error message
									jQueryElm.after('<div id="' + inlineMessageElementId + '" class="' + fullOptions.inlineMessageCssClass + '">' + validationRule.errorMessage + '</div>');	
									if (fullOptions.inlineShowSpeed != ""){
										jQuery("#" + inlineMessageElementId).hide();
										jQuery("#" + inlineMessageElementId).show(fullOptions.inlineShowSpeed);	
									}
								}
								
								break;
							}
						}
					}
				}	
			}
			
		});
		
		if (!validatedOK && fullOptions.showSummary){
			// Show the message summary
			var summaryHtml = "";
			if (fullOptions.summaryMessage != ""){
				summaryHtml = fullOptions.summaryMessage;
			}
			
			summaryHtml += "<ul>";
			for(var i=0;i<messagesForSummary.length; i++){
				summaryHtml += "<li><a href=\"#\" onclick=\"location.hash = '#" + fieldsForSummary[i] + "'; jQuery('#" + fieldsForSummary[i] + "')[0].focus(); return false;\">" + messagesForSummary[i] + "</a></li>";
			}
			summaryHtml += "</ul>";
			
			jQuery("#" + fullOptions.summaryElementId).html(summaryHtml).show();
			
			scrollTo = fullOptions.summaryElementId;
		}
		
		if (scrollTo != ""){
			location.hash = "#" + scrollTo;
		}
		
		if (focusField != ""){
			jQuery("#" + focusField)[0].focus();
		}
		
		return validatedOK;
	}
};


//
// jQuery object method extensions
//
jQuery.fn.validationAideEnable = function(validationRules, options, preFieldValidation, postFieldValidation){
	jQuery.validationAide.resetForm("#" + this[0].id, options);
	this.unbind("submit");
	this.bind("submit", function(){ return jQuery.validationAide.validateForm("#" + this.id, validationRules, options, preFieldValidation, postFieldValidation); });
	return this;
};

jQuery.fn.validationAideDisable = function(){
	this.unbind("submit");
	return this;
};

jQuery.fn.validationAideDisableOnClick = function(formId){
	this.unbind("click");
	this.bind("click", function(){ jQuery(formId).unbind("submit"); });
	return this;
};

jQuery.fn.validationAideEnableOnClick = function(formId, validationRules, options, preFieldValidation, postFieldValidation){
	jQuery.validationAide.resetForm(formId, options);
	this.unbind("click");
	this.bind("click", function(){ jQuery(formId).validationAideEnable(validationRules, options, preFieldValidation, postFieldValidation); });
	return this;
};