/**
 * Utils_Js_Jquery_Validation_Validate
 *
 * @uses       Jquery
 * @package    Utils
 * @subpackage Validation
 * @copyright  Copyright (c) Christof Coetzee
 * @license    GNU CC
 */
 function Utils_Js_Jquery_Validation_Validate_Types(func, fieldName, fieldVal, valParams){
	fieldVal = fieldVal.toString();
	switch(func){
	
	case 'isCheckable':   
		
    	return($('#'+fieldName).attr('type') == 'checkbox' || $('#'+fieldName).attr('type') == 'radio') 	
    break;
    
    case 'isChecked':    
    	return $('#'+fieldName).attr('checked');
    break;
    
    case 'requiredIfField':
    //can in theory only match one foreign field
    allForeingFieldsMatch = false;
    
    	$.each(valParams, function(fFieldName, fFieldVal){
    	
    		if(Utils_Js_Jquery_Validation_Validate_Types('isCheckable', fFieldName, fieldVal, fFieldVal)){
    		
    		isChecked = Utils_Js_Jquery_Validation_Validate_Types('isChecked', fFieldName, fieldVal, fFieldVal);
    			
    			if(!isChecked && fFieldVal == '@notChecked'){
    			allForeingFieldsMatch = true; 
    			}
    			if(isChecked && $('#'+fFieldName).val() == fFieldVal && fFieldVal != '@notChecked'){
		    	allForeingFieldsMatch = true; 
		    	}
		   
	    	}else{
	    	allForeingFieldsMatch = ($('#'+fFieldName).val() == fFieldVal);
	    	}
	    	
	   });
	   	
     return allForeingFieldsMatch;
           
    break;
    //tipically used for password retype match
    case 'matchOtherField':
    	
    	return (fieldVal == $('#'+valParams[0]).val());
    
    break;
    
    case 'digits':
	return fieldVal.match(/\b\d+\b/);
	break;
	
	case 'int':
	return fieldVal.toString().match(/\b\d+\b/);
	break;
	
	case 'float':
	return fieldVal.match(/[-+]?\b(?:[0-9]*\.)?[0-9]+\b/);
	break;
	
	case 'alnum':
	return fieldVal.match(/[a-z]+[0-9]+/i);
	break;
	
	case 'alpha':
	return fieldVal.match(/[a-z]+/i);
	break;
	
	case 'notEmpty':
		return (fieldVal != "");
	break;
	//do a numeric or alpha test
	case 'greaterThan':
		//is a number
		if(!isNaN(parseFloat(fieldVal))){
		return (parseFloat(fieldVal) > parseFloat(valParams));
		}else{
		return (fieldVal.length > parseFloat(valParams));
		}
	break;
	//do a numeric or alpha test
	case 'lessThan':
	
		if(!isNaN(parseFloat(fieldVal))){
		return (parseFloat(fieldVal) < parseFloat(valParams));
		}else{
		return (fieldVal.length < parseFloat(valParams));
		}
	break;
	
	case 'between':
	//effectively matching boolean returns
		return (Utils_Js_Jquery_Validation_Validate_Types('greaterThan', fieldName, fieldVal, valParams[0]) == Utils_Js_Jquery_Validation_Validate_Types('lessThan', fieldName, fieldVal, valParams[1]));
	break;
	//do a alpha test
	case 'stringLength':
		return (fieldVal.length >=  valParams[0] && fieldVal.length <=  valParams[1]);
	break;
	
	case 'emailAddress':
	return(fieldVal.match(/\b[A-Z0-9._%-]+@[A-Z0-9_%-]+\.[A-Z]{2,4}\b/i));
	break;
	
	case 'url':
		return (fieldVal.match(/^((http:\/\/)+|^(https:\/\/))+?([a-zA-Z0-9])+\.+/));
	break;
	
	case 'time':
		return (fieldVal.match(/\b[0-9]{2}\:[0-9]{2}\:[0-9]{2}\b/));
	break;	
	
	case 'date': 
		return (fieldVal.match(/\b(19|20)[0-9]{2}[- \/.](0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])\b/));
	break;
	
	case 'regex': 
		var re = new RegExp(valParams.toString());	
		return (re.test(fieldVal));
	break;
	
	default :
	
	//alert ('no validation type found for : ' + func); return false;
	return true;
	break;
	
	}	

}
//-----------------------------------------------------------------------------------------------------------
function Utils_Js_Jquery_Validation_Required(val, fieldName, fieldObjectRules){

temp = fieldObjectRules.rules.required; 
dependOtherField = false;

	 $.each(fieldObjectRules.rules, function (rulesName, rulesParams){
	
	   if(rulesName == 'requiredIfField'){
	   temp = Utils_Js_Jquery_Validation_Validate_Types('requiredIfField', fieldName, val, rulesParams);
	   dependOtherField = true;
	   }
	      
	});

	//field is set as not required, but now it contains a value, so set as required
	if($.trim(val.toString()) != '' && !fieldObjectRules.rules.required && !dependOtherField){
	temp = true;
	} 
	
return temp;

}
//-----------------------------------------------------------------------------------------------------------
function Utils_Js_Jquery_Validation_Parse(event){

formOptions = event.data;
applyErrorsToDivs = false;

	/*
	lets reset the 'alert' error messages
	the submit event will parse all fields anyway
	*/	
    UtilsJsErrorMessage = new Array();
	
	
	try{	
		
		var processHash = function(){
		
			$.each(formOptions, function (rowNum, objectList){
			
			/*
			a field might have more than 1 validators, 
			all needs to be satisfied before its considered valid	
			*/	
			thisFieldValidatorFalseCount= 0;
				
			fieldName = formOptions[rowNum].name;
			applyErrorsToDivs = formOptions[rowNum].applyErrorsToDivs;
			
			currVal = $('#'+fieldName).val();
			
			//check if static or on-the-fly required has been set
			fieldIsRequired = Utils_Js_Jquery_Validation_Required(currVal, fieldName, objectList);
									
			   $.each(objectList.rules, function (rulesName, rulesParams){
			 				 
					  if(rulesName != 'requiredIfField' && rulesName != 'required' && fieldIsRequired){
					  		  	 	
					   		if(!Utils_Js_Jquery_Validation_Validate_Types(rulesName, fieldName, currVal,rulesParams)){
					   		thisFieldValidatorFalseCount++; 
					   		}
					   		
					   		if(Utils_Js_Jquery_Validation_Validate_Types('isCheckable', fieldName, currVal,rulesParams) && !Utils_Js_Jquery_Validation_Validate_Types('isChecked', fieldName, currVal,rulesParams)){
					   		thisFieldValidatorFalseCount++;
					   		}
					   		
					  }  
					  	
			   	  	if(thisFieldValidatorFalseCount > 0){
   	
				   		if(applyErrorsToDivs){
				   		$('#'+fieldName+'_ErrorDiv').html(formOptions[rowNum].errorMessage);
				   		$('#'+fieldName+'_ErrorDiv').fadeIn('slow');
				   		}
				   	
				   		//this will only be used by the full loop, when the form is submitted 
				   		UtilsJsErrorMessage.push({"name" : fieldName, "error" : formOptions[rowNum].errorMessage});
				   
				   	}else{
				 	
				   		if(applyErrorsToDivs){
				   		//dont add a JQuery callback function here as it causes unpredicatble results
				   		$('#'+fieldName+'_ErrorDiv').fadeOut('slow');
				   		}
				   	}
			    
			   });
			});
	    
	    }
    }catch(e){
    alert(e);
    return false;
    }    
  
  //PROCESS ALL FIELDS FROM JSON HASH - MASTER CALL  
  processHash(); 
  
  //this function is also binded to the submit event - in that case run below
   if(event.data.isSubmitAction && UtilsJsErrorMessage.length > 0){
	
	  //master setting indicate that errors should be displayed in am alert dialog box 
  	  if(!applyErrorsToDivs){
  	  
  	  tmpErrorString = '';
  	  tmpFieldNameList = '';
  	    	  
	  	  $.each(UtilsJsErrorMessage, function (rowNum, values){
	  	  	
	  	  	//ignore duplicate error field messages
	  	  	if(UtilsJsErrorMessage[rowNum].name != tmpFieldNameList){
	  	  	tmpErrorString += "- "+UtilsJsErrorMessage[rowNum].error+"\n\r";
	  	  	tmpFieldNameList = UtilsJsErrorMessage[rowNum].name;
	  	  	}
	  	 	  	  	
	  	  });
	   	  	
	  alert(tmpErrorString);
	  }

 //lets return the boolean for the form bubbling  
  return false;
  }else if(UtilsJsErrorMessage.length < 1){ 
  
  	if(event.data.ajaxSubmit == true){
  	
  		switch(this.method.toUpperCase()){	
  		case 'POST' :
  		new Utils_Js_Jquery_Ajax_Post(this.action, this.id);
  		break;
  		case 'GET' :
  		new Utils_Js_Jquery_Ajax_Get(this.action, this.id);
  		break;
  		default :
  		alert('no method post or get found for form'+this.id);
  		break;
  		}
  	//we still need to return false else the normal form submission will fire and redirect
  	return false;	
  	}else{
  	return true;
  	}
  	
  }
   
}

//-----------------------------------------------------------------------------------------------------------

function Utils_Js_Jquery_Validation_Validate_Init(formName, formOptions, onFieldBlur, applyErrorsToDivs, ajaxSubmit){

var fullHash = new Array();
	
	try{
		$.each(formOptions, function (fieldName, Params){
		
		var temp = {"name": fieldName, "rules" : Params.Rules, "errorMessage": Params.ErrorMessage, "applyErrorsToDivs" : applyErrorsToDivs, "onFieldBlur" : onFieldBlur};	
		fullHash.push(temp);
		
			//tipicallly used where you need validation as the user completes an individual field
			if(onFieldBlur){
			$("#"+fieldName).bind("blur", new Array(temp), Utils_Js_Jquery_Validation_Parse);
				/*
				if this div contains content it is probably a server-side message
				then we dont want to hide it
				*/
				if($.trim($('#'+fieldName+'_ErrorDiv').html()) == ''){
				$('#'+fieldName+'_ErrorDiv').css({"display" : "none"});
				}
				
			}	
					
		});
		
		//we still need the full binding here for when the user submits the form by pressing enter or clicking the submit button
		$("#"+formName).bind("submit", $.extend(fullHash,{"isSubmitAction" : true, "ajaxSubmit" : ajaxSubmit}), Utils_Js_Jquery_Validation_Parse);
		
	}catch(e){
	alert(e);
	return false;
	}	
	
}


