/**
 * 
 * @author 	Gabriel Marinescu <migabriel.84@gmail.com>
 * @author 	<>
 * @version 0.1.1
 * @addon 	jQuery 
 * 
 * Form field validator 
 * Features that nead to be implemented
 * 		- ajax validator
 * 		- regex (custom validator)
 * 		- natural
 * 		- link
 * 		- host
 * 		- name
 * 		- lower_case
 * 		- upper_case
 */


(function($){
	/**
	 * Instance $('.'+class).valid("form_name", methode);
	 * 	where methode is : 	- 'alert' : display methode error in alert;
	 * 						- 'name/rule' 	error message is displayed into 
	 * 										a span element the id is name and role Ex.      
	 * 	
	 * @access public
	 */
	
	var ajaxReturned 	= Array();
	var verifyAjaxCount = 0;
	var verifyAjax 		= false;
	var maxTimeout 		= 10000;
	var currentTime 	= 0;
	var formID 			= '';
	var displayMethod 	= 'alert';
	var params			= new Object();
	
	$.fn.valid = function(formElement, methode){
		var className;		
		var Valid = true;
		formID = formElement;
		displayMethod = methode;
		this.each(function() {
			// Get necesary information about current element
			
			if($(this).attr("type")=='checkbox') 
			{
				
				if($(this).attr("checked")==true)
				{
					params[$(this).attr("name")] = $(this).attr("value");
				}
			} 
			else 
			{
				params[$(this).attr("name")] = $(this).attr("value");
			}
			
			className 		= $(this).attr("class").split(" ");
			var messages 	= $(this).attr("title").split('|');
			var rules 		= className[0].split("|");
			//var crtElement  = $('[name='+$(this).attr("name")+']')
			for(var i=0; i<rules.length; i++)
			{
				var message = ""
				if(messages[i]!=null){
					message = messages[i];
				}
				if(isValid($(this), rules[i], message)==false){
					Valid = false;
					break;
				}
			}
			
		});
		if(Valid==false){
			return false;
		}
		
		var event = false;
		if(className!=undefined)
		{
			if(className[1]!=undefined)
			{
				event = className[1]; 
			} else {
				event = className[0];
			}
		}
		$('#event').remove();
		$('form[name='+formElement+']').append('<input type="hidden" style="display:none;" id="event" name="event" value="'+event+'" />');
		//alert(verifyAjax);
		if (verifyAjax)
		{
			currentTime = 0;
			timeInterval = setTimeout(mainLoop, 100)
		}
		else
			return params;
	}// ~valid
	
	
	function displayMessage(message, id)
	{
		
		switch(displayMethod)
		{
			case 'alert':
				alert(message);
			break;
			case 'name/rule':
				$('#'+id).css('display', 'block');
			break;
		}
	}
	
	function hideMessage(id)
	{
		switch(displayMethod)
		{
			case 'name/rule':
				$('#'+id).css('display', 'none');
			break;
		}
	}
	
	
	function mainLoop()
	{
		
		var doSubmit = true;
		var isValid = true;
		for (var i=1; i<= verifyAjaxCount; i++)
		{
			if (ajaxReturned[i] == 0)
				doSubmit = false;
			if (ajaxReturned[i] == -1)
				isValid = false;
		}
		
		if (doSubmit)
		{
			clearTimeout(timeInterval);
			if (isValid)
				document.forms[formID].submit();
		}
		
		if (currentTime > maxTimeout )
			clearTimeout(timeInterval);
		
		currentTime+=100;
	}
	/**
	 * Private method
	 */
	function isValid(element, rule, message)
	{
		
		var inputName 	= element.prev().html();
		
		var RuleType = rule.match(/^\w+/); 
		var Argument = rule.match(/\[(.*)\]/);
		if(Argument !=null)
			Argument = Argument[1].toString();
		else Argument = "";
		if(RuleType !=null)
			RuleType = RuleType[0].toString();
		else RuleType = "";
		
		switch(RuleType){
			case 'required':
				if(element.attr('type')=='checkbox')
				{
					if(element.attr('checked')==false)
					{
						if(message=='')
							displayMessage('The field '+inputName+' is required', element.attr('name')+'required');
						displayMessage(message, element.attr('name')+'_required');
						return false;
					}
				} else {
					if(element.val().length==0 || element.val() == element.attr('title'))
					{
						if(message=='')
							displayMessage('The field '+inputName+' is required', element.attr('name')+'required');
						displayMessage(message, element.attr('name')+'_required');
						return false;
					}
				}
				hideMessage(element.attr('name')+'_required');
			break;
			case 'numeric':
				if(element.val().length!=0){
					var str = element.val().toString();
					if(str.match(/^(-[0-9]+\.[0-9]+|[0-9]+\.[0-9]+|[0-9]+)$/)==null){
						if(message=='')
							message = 'The field '+inputName+' is not numeric';
						displayMessage(message, element.attr('name')+'_numeric');
						return false;
					}
				}
				hideMessage(element.attr('name')+'_numeric');
			break;
			case 'alphaNumPlus':
				if(element.val().length!=0){
					var str = element.val().toString();
					if(str.match(/^([A-Za-z0-9_]+)$/)==null){
						if(message=='')
							message = 'The field '+inputName+' must be AlphaNumeric';
						displayMessage(message, element.attr('name')+'_alphaNumPlus');
						return false;
					}
				}
				hideMessage(element.attr('name')+'_alphaNumPlus');
			break;
			case 'email':
				if(element.val().length!=0){
					if(element.val().search(/^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/)==-1){
						if(message=='')
							message = 'The field is '+inputName+' not a valid email address';
						displayMessage(message, element.attr('name')+'_email');
						return false;
					}
				}
				hideMessage(element.attr('name')+'_email');
			break;
			case 'match':
				if($('input[name='+Argument+']').val()!=element.val()){
						if(message=='')
							message = 'The field is '+inputName+' and '+$('#'+Argument).prev().html()+' doesn\'t match';
						displayMessage(message, element.attr('name')+'_match');
					return false;
				}
			break;
			case 'ajax':
				verifyAjaxCount++;
				ajaxReturned[verifyAjaxCount] = 0;
				verifyAjax = true;
				$.get(Argument, null, function (result){
					ajaxReturned[verifyAjaxCount] = 1;
					if(result.match(/result=\[\w+\]/).toString()!="result=[true]")
					{
						ajaxReturned[verifyAjaxCount] = -1;
						//alert(result.match(/result=\[\w+\]/).toString());
						if(message=='')
							message ='The field '+inputName+' is not valid';
						displayMessage(message, element.attr('name')+'_ajax');
					} else {
						hideMessage(element.attr('name')+'_ajax');
						ajaxReturned[verifyAjaxCount] = 1;
					}
				});
			break;
			case 'maximlen':
					if(element.val().length > Argument){
						if(message!="")
							message = 'The field '+inputName+' have to be no longer then '+Argument+' chars!';
						displayMessage(message, element.attr('name')+'_maximlen');
						return false;
					}
					hideMessage(element.attr('name')+'_maximlen');
			break;
			case 'minimlen':
				if(parseInt(element.val().length, 10) < parseInt(Argument,10)){
					if(message=="")
						message = 'The field '+inputName+' have to be at least '+Argument+' chars!';
					displayMessage(message, element.attr('name')+'_minimlen');
					return false;
				}
				hideMessage(element.attr('name')+'_minimlen');
			break;
			case 'host':
				if(element.val().match(/\w+\.\w+\.\w{2,3}/)!=-1 &&  element.val().match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)!=-1 ){
					if(message=="")
						message = 'The field '+inputName+' is not a valid host address!';
					displayMessage(message, element.attr('name')+'_host');
					return false;
				}
				hideMessage(element.attr('name')+'_host');
			break;
			case 'link':
				if(element.val().match(/^http:\/\//)==null){
					if(message=="")
						message = 'The field '+inputName+' is not a valid host address!';
					displayMessage(message, element.attr('name')+'_link');
					return false;
				}
				hideMessage(element.attr('name')+'_link');
			break;
		}//~switch
		return true;
	}// ~isValid
})(jQuery);