/*
 * Inline Form Validation Engine, jQuery plugin
 * 
 * Copyright(c) 2009, Cedric Dugas
 * http://www.position-relative.net
 *	
 * Form validation engine witch allow custom regex rules to be added.
 * Licenced under the MIT Licence
 */

$j(document).ready(function() {

	// SUCCESS AJAX CALL, replace "success: false," by:     success : function() { callSuccessFunction() }, 
	$j("[class^=validate]").validationEngine({
		success :  false,
		failure : function() {}
	})
});

jQuery.fn.validationEngine = function(settings) {
	if($j.validationEngineLanguage){					// IS THERE A LANGUAGE LOCALISATION ?
		allRules = $j.validationEngineLanguage.allRules
	}else{
		allRules = {"required":{    			  // Add your regex rules here, you can take telephone as an example
							"regex":"none",
							"alertText":" Preenchimento obrigatorio.",
							"alertTextCheckboxMultiple":" Por favor escolha uma opcao.",
							"alertTextCheckboxe":" Por favor escolha uma opcao."},
						"length":{
							"regex":"none",
							"alertText":" Permitido somente de ",
							"alertText2":" a ",
							"alertText3": " caracteres."},
						"numExato":{
							"regex":"none",
							"alertText":" Informacao invalida."},
						"cpf":{
							"regex":"none",
							"alertText":" CPF invalido."},
						"minCheckbox":{
							"regex":"none",
							"alertText":" Excedeu o numero maximo permitido."},	
						"confirm":{
							"regex":"none",
							"alertText":" Os campos estao diferentes."},		
						"telephone":{
							"regex":"/^[0-9\-\(\)\ ]+$/",
							"alertText":" Numero de telefone invalido."},	
						"email":{
							"regex":"/^[a-zA-Z0-9_\.\-]+\@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]{2,4}$/",
							"alertText":" E-mail invalido."},	
						"date":{
                             "regex":"/^[0-9]{1,2}\-\[0-9]{1,2}\-\[0-9]{4}$/",
                             "alertText":" Data invalida, deve ser no formato DD/MM/AAAA."},
						"onlyNumber":{
							"regex":"/^[0-9\ ]+$/",
							"alertText":" Somente numeros."},	
						"noSpecialCaracters":{
							"regex":"/^[0-9a-zA-Z]+$/",
							"alertText":" Nao e permitido caracteres especiais."},	
						"onlyLetter":{
							"regex":"/^[a-zA-Z\ \']+$/",
							"alertText":" Somente letras."}
					}	
	}

 	settings = jQuery.extend({
		allrules:allRules,
		success : false,
		failure : function() {}
	}, settings);	


	$j("form").bind("submit", function(caller){   // ON FORM SUBMIT, CONTROL AJAX FUNCTION IF SPECIFIED ON DOCUMENT READY
		if(submitValidation(this) == false){
			if (settings.success){
				settings.success && settings.success(); 
				return false;
			}
		}else{
			settings.failure && settings.failure(); 
			return false;
		}
	})
	$j(this).not("[type=checkbox]").bind("blur", function(caller){loadValidation(this)})
	$j(this+"[type=checkbox]").bind("click", function(caller){loadValidation(this)})
	
	var buildPrompt = function(caller,promptText) {			// ERROR PROMPT CREATION AND DISPLAY WHEN AN ERROR OCCUR
		var divFormError = document.createElement('div')
		var formErrorContent = document.createElement('div')
		var arrow = document.createElement('div')
		
		
		$j(divFormError).addClass("formError")
		$j(divFormError).addClass($j(caller).attr("name"))
		$j(formErrorContent).addClass("formErrorContent")
		$j(arrow).addClass("formErrorArrow")

		$j("body").append(divFormError)
		$j(divFormError).append(arrow)
		$j(divFormError).append(formErrorContent)
		$j(arrow).html('<div class="line10"></div><div class="line9"></div><div class="line8"></div><div class="line7"></div><div class="line6"></div><div class="line5"></div><div class="line4"></div><div class="line3"></div><div class="line2"></div><div class="line1"></div>')

		$j(formErrorContent).html(promptText)
	
		callerTopPosition = $j(caller).offset().top;
		callerleftPosition = $j(caller).offset().left;
		callerWidth =  $j(caller).width()
		callerHeight =  $j(caller).height()
		inputHeight = $j(divFormError).height()

		callerleftPosition = callerleftPosition + callerWidth -27
		callerTopPosition = callerTopPosition  -inputHeight -10
	
		$j(divFormError).css({
			top:callerTopPosition,
			left:callerleftPosition,
			opacity:0
		})
		$j(divFormError).fadeTo("fast",0.85);
	};
	var updatePromptText = function(caller,promptText) {	// UPDATE TEXT ERROR IF AN ERROR IS ALREADY DISPLAYED
		updateThisPrompt =  $j(caller).attr("name")
		$j("."+updateThisPrompt).find(".formErrorContent").html(promptText)
		
		callerTopPosition  = $j(caller).offset().top;
		inputHeight = $j("."+updateThisPrompt).height()
		
		callerTopPosition = callerTopPosition  -inputHeight -10
		$j("."+updateThisPrompt).animate({
			top:callerTopPosition
		});
	}
	var loadValidation = function(caller) {		// GET VALIDATIONS TO BE EXECUTED
		
		rulesParsing = $j(caller).attr('class');
		rulesRegExp = /\[(.*)\]/;
		getRules = rulesRegExp.exec(rulesParsing);
		str = getRules[1]
		pattern = /\W+/;
		result= str.split(pattern);	
		
		var validateCalll = validateCall(caller,result)
		return validateCalll
		
	};
	var validateCall = function(caller,rules) {	// EXECUTE VALIDATION REQUIRED BY THE USER FOR THIS FILED
		var promptText =" <span style='color:#515151;font-weight:bold;'>|</span> "	
		var indicePromptText = 1;
		var prompt = $j(caller).attr("name");
		var caller = caller;
		isError = false;
		callerType = $j(caller).attr("type");
		
		for (i=0; i<rules.length;i++){
			switch (rules[i]){
			case "optional": 
				if(!$j(caller).val()){
					closePrompt(caller)
					return isError
				}
			break;
			case "required": 
				_required(caller,rules);
			break;
			case "custom": 
				 _customRegex(caller,rules,i);
			break;
			case "length": 
				 _length(caller,rules,i);
			break;
			case "numExato": 
				 _numExato(caller,rules,i);
			break;
			case "cpf": 
				 _cpf(caller,rules,i);
			break;
			case "minCheckbox": 
				 _minCheckbox(caller,rules,i);
			break;
			case "confirm": 
				 _confirm(caller,rules,i);
			break;
			default :;
			};
		};
		if (isError == true){
			
			if($j("input[name="+prompt+"]").size()> 1 && callerType == "radio") {		// Hack for radio group button, the validation go the first radio
				caller = $j("input[name="+prompt+"]:first")
			}
			($j("."+prompt).size() ==0) ? buildPrompt(caller,promptText)	: updatePromptText(caller,promptText)
		}else{
			closePrompt(caller)
		}		
		
		/* VALIDATION FUNCTIONS */
		function _required(caller,rules){   // VALIDATE BLANK FIELD
			var callerType = $j(caller).attr("type")
			
			if (callerType == "text" || callerType == "password" || callerType == "textarea"){
				
				if(!$j(caller).val()){
					isError = true
					promptText += indicePromptText+': '+settings.allrules[rules[i]].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					indicePromptText++;
				}	
			}
			if (callerType == "radio" || callerType == "checkbox" ){
				callerName = $j(caller).attr("name")
		
				if($j("input[name="+callerName+"]:checked").size() == 0) {
					isError = true
					if($j("input[name="+callerName+"]").size() ==1) {
						promptText += indicePromptText+': '+settings.allrules[rules[i]].alertTextCheckboxe+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					}else{
						 promptText += indicePromptText+': '+settings.allrules[rules[i]].alertTextCheckboxMultiple+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					}	
					indicePromptText++;
				}
			}	
			if (callerType == "select-one") { // added by paul@kinetek.net for select boxes, Thank you
					callerName = $j(caller).attr("name");
				
				if(!$j("select[name="+callerName+"]").val()) {
					isError = true;
					promptText += indicePromptText+': '+settings.allrules[rules[i]].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					indicePromptText++;
				}
			}
			if (callerType == "select-multiple") { // added by paul@kinetek.net for select boxes, Thank you
					callerName = $j(caller).attr("id");
				
				if(!$j("#"+callerName).val()) {
					isError = true;
					promptText += indicePromptText+': '+settings.allrules[rules[i]].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					indicePromptText++;
				}
			}
		}
		function _customRegex(caller,rules,position){		 // VALIDATE REGEX RULES
			var customRule = rules[position+1]
			var pattern = eval(settings.allrules[customRule].regex)
			if(!pattern.test($j(caller).attr('value')) && $j(caller).attr('value')!=''){
				isError = true
				promptText += indicePromptText+': '+settings.allrules[customRule].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
				indicePromptText++;
			}
		}
		function _confirm(caller,rules,position){		 // VALIDATE FIELD MATCH
			var confirmField = rules[position+1]
			
			if($j(caller).attr('value') != $j("#"+confirmField).attr('value')){
				isError = true
				promptText += indicePromptText+': '+settings.allrules["confirm"].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
				indicePromptText++;
			}
		}
		function _length(caller,rules,position){    // VALIDATE LENGTH
		
			var startLength = eval(rules[position+1])
			var endLength = eval(rules[position+2])
			var feildLength = $j(caller).attr('value').length

			if((feildLength<startLength || feildLength>endLength) && $j(caller).attr('value')!=''){
				isError = true
				promptText += indicePromptText+': '+settings.allrules["length"].alertText+startLength+settings.allrules["length"].alertText2+endLength+settings.allrules["length"].alertText3+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
				indicePromptText++;
			}
		}
		function _numExato(caller,rules,position){    // VALIDATE LENGTH
			var feildLength = $j(caller).attr('value').length;
			var length = eval(rules[position+1]);
			if(feildLength!=length && $j(caller).attr('value')!=''){
				isError = true
				promptText += indicePromptText+': '+settings.allrules["numExato"].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
				indicePromptText++;
			}
		}
		function _cpf(caller,rules,position){
			if($j(caller).attr("value")!=''){
				var validacao = 1;
				var CPF = $j(caller).attr("value");
				CPF = CPF.replace('.','').replace('.','').replace('.','').replace('-','').replace(' ','');
				if (CPF.length != 11 || CPF == "00000000000" || CPF == "11111111111" ||
					CPF == "22222222222" ||	CPF == "33333333333" || CPF == "44444444444" ||
					CPF == "55555555555" || CPF == "66666666666" || CPF == "77777777777" ||
					CPF == "88888888888" || CPF == "99999999999")
					validacao = 0;
				var soma = 0;
				for (i=0; i < 9; i ++) soma += parseInt(CPF.charAt(i)) * (10 - i);
				var resto = 11 - (soma % 11);
				
				if (resto == 10 || resto == 11) resto = 0;
				if (resto != parseInt(CPF.charAt(9))) validacao = 0;
				
				soma = 0;
				for (i = 0; i < 10; i ++) soma += parseInt(CPF.charAt(i)) * (11 - i);
				resto = 11 - (soma % 11);
				
				if (resto == 10 || resto == 11) resto = 0;
				if (resto != parseInt(CPF.charAt(10))) validacao = 0;
				if(validacao==0){
					isError = true
					promptText += indicePromptText+': '+settings.allrules["cpf"].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
					indicePromptText++;
				}
			}
		}
		function _minCheckbox(caller,rules,position){    // VALIDATE CHECKBOX NUMBER
		
			var nbCheck = eval(rules[position+1])
			var groupname = $j(caller).attr("name")
			var groupSize = $j("input[name="+groupname+"]:checked").size()
			
			if(groupSize > nbCheck){	
				isError = true
				promptText += indicePromptText+': '+settings.allrules["minCheckbox"].alertText+' <span style=\'color:#515151;font-weight:bold;\'>|</span> ';
				indicePromptText++;
			}
		}

		return(isError) ? isError : false;
	};
	var closePrompt = function(caller) {	// CLOSE PROMPT WHEN ERROR CORRECTED
		closingPrompt = $j(caller).attr("name")

		$j("."+closingPrompt).fadeTo("fast",0,function(){
			$j("."+closingPrompt).remove()
		});
	};
	var submitValidation = function(caller) {	// FORM SUBMIT VALIDATION LOOPING INLINE VALIDATION
		var stopForm = false
		$j(caller).find(".formError").remove()
		var toValidateSize = $j(caller).find("[class^=validate]").size()
		
		$j(caller).find("[class^=validate]").each(function(){
			var validationPass = loadValidation(this)
			return(validationPass) ? stopForm = true : "";	
		});
		if(stopForm){							// GET IF THERE IS AN ERROR OR NOT FROM THIS VALIDATION FUNCTIONS
			destination = $j(".formError:first").offset().top;
			$j("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, 1100)
			return true;
		}else{
			return false
		}
	};
};
