var Validation = {

	timer: 0,
	
	formFields: new Array(),

	modelName: "",

	submitId: "",

	formId: "",

	usernameRequest: "",

	emailRequest: "",

	usernameRequestResult: true,

	emailRequestResult: true,

	ajaxRequestUrl: "users",

	hideMessage: function(tag)
	{
		this.hideSubmitMessage();
		d=$("#"+tag+"Error")
		if (d)
		{
			d.html('');
			d.css('display', 'none');
		}	
	},
	
	showMessage: function(tag, message)
	{
		d=$("#"+tag+"Error")
		if (d)
		{
			d.html('<div class="error-message">'+message+'</div>');
			d.css('display', 'block');
		}	
	},
	
	hideSubmitMessage: function()
	{
		d=$("#SubmitError")
		if (d)
		{
			d.html('');
			d.css('display', 'none');
		}	
	},
	
	add: function(tag, message, rule, params) 
	{
		if($("#"+tag))
		{
			a=new Array(5);
			a["tag"]=tag;
			a["message"]=message;
			a["rule"]=rule;
			a["params"]=params;
			a["validates"]=true;
			a["doValidate"]=true;
	
			if (!this.formFields[tag])
				this.formFields[tag]=new Array();
			this.formFields[tag].push(a);		
			
			$("#"+tag).blur(function(){
				Validation.validateTag(tag);
			});		
			
		  	$("#"+tag).keyup(function(){
				if (Validation.timer)
					clearTimeout(Validation.timer);		
				Validation.timer=setTimeout(function(){
					Validation.validateTag(tag);
				},1000);
			});
	
		  	$("#"+tag).mouseup(function(){
				if (Validation.timer)
					clearTimeout(Validation.timer);		
				Validation.timer=setTimeout(function(){
					Validation.validateTag(tag);
				},1000);
			});
		}
	},
	
	init: function(formId, submitId, message, fn)
	{
		this.modelName=fn;
		this.formId=formId;
		this.submitId=submitId;
		if ($("#"+this.submitId))
		{
			$("#"+this.submitId).attr('disabled', false);
			$("#"+this.formId).submit(function(){
				validation=true;
				var it;
				for (it in Validation.formFields)
				{
					if (Validation.formFields[it][0])
					{
						if (Validation.formFields[it][0]["tag"])
						{
							for(var i=0; i<	Validation.formFields[it].length; i++)
							{
								if (Validation.formFields[it][i]["doValidate"])
								{
									if (!Validation.doValidate(Validation.formFields[it][i]["tag"], Validation.formFields[it][i]["message"], Validation.formFields[it][i]["rule"], Validation.formFields[it][i]["params"]))
									{
										validation=false;
										Validation.formFields[it][i]["validates"]=false;
										break;
									}
								}
							}
						}
					}
				}
				if($("#"+Validation.formId))
				{
					if (validation==true)
					{
						Validation.hideSubmitMessage();	
						$("#"+Validation.submitId).attr('disabled', true);
						formSend();
						return true;
					}
					else
					{
						Validation.showMessage(Validation.submitId,message);
						return false;	
					}
				}					
				return false;	
			});
		}	
	},
	
	validateTag: function(tag)
	{
		validation=true;
		if (this.formFields[tag])
		{
			for(i=0; i<	this.formFields[tag].length; i++)
			{
				if (this.formFields[tag][i]["doValidate"]) {
					if (this.doValidate(this.formFields[tag][i]["tag"], this.formFields[tag][i]["message"], this.formFields[tag][i]["rule"], this.formFields[tag][i]["params"]) == false) {
						validation = false;
						break;
					}
				}
			}
		}
		return validation;
	},
	
	doValidate: function(tag, message, rule, params)
	{
		if (!this.validates(tag, rule, params, message))
		{
			this.showMessage(tag, message)
			return false;
		}
		else 
		{
			this.hideMessage(tag)	
			return true;
		}
	},
	
	getValue: function(id)
	{
		el=$("#"+id);
		val='';
		if (el)
		{
			if (!el.attr("type"))
			{
				e=el.find('input[type=radio]');
				if (e)
				{
					e.each(function(i){
						r=$(this);
						if ((r.attr("type")=="radio") && (r.attr("checked")))
							val=r.val();
					});
				}
	
				if (!val)
				{
					e=el.find('select');
					if (e)
					{						
						if (e.length==3)
						{
							if ((e.eq(0).val()) && (e.eq(1).val()) && (e.eq(2).val()))
								val=e.eq(0).val()+"-"+e.eq(1).val()+"-"+e.eq(2).val();
						}
						else if (e.length==5)
						{
							if ((e.eq(0).val()) && (e.eq(1).val()) && (e.eq(2).val()) && (e.eq(3).val()) && (e.eq(4).val()))
								val=e.eq(0).val()+"-"+e.eq(1).val()+"-"+e.eq(2).val()+" "+e.eq(3).val()+":"+e.eq(4).val();
						}
					}
				}
			}
			else
			{
				switch(el.attr("type"))
				{
					case "checkbox":
						if (el.attr("checked")==true)
							val=1;
					break;
					case "select-one":
					case "select-multiple":
						if (el.val())
							val=el.val();
					break;
					default:
						if (el.val())
							val=el.val();
						else if (el.text())
							val=el.text();
					break;
				}
			}
				
			return val;
		}
		else
			return false;
	},
	
	validates: function(id, rule, params, message)
	{
		if ($("#"+id).length==0)
			return true;

		val=this.getValue(id);
		/*
		if (!val)
		{
			if ((rule=='required'))
				return false;
			else if (rule!='confirmPassword')
				return true;
		}
		*/
		switch(rule)
		{
			case 'between':
				return (((val.length)>=eval(params.param1)) && ((val.length)<=eval(params.param2))) ? true:false
			break;
			case 'comparison':
				if (isNaN(val))
					return false;

					switch(params.param1) {
						case 'isgreater':
						case '>':
							return (eval(val)>eval(params.param2))?true:false
						break;
						case 'isless':
						case '<':
							return (eval(val)<eval(params.param2))?true:false
						break;
						case 'greaterorequal':
						case '>=':
							return (eval(val)>=eval(params.param2))?true:false
						break;
						case 'lessorequal':
						case '<=':
							return (eval(val)>=eval(params.param2))?true:false
						break;
						case 'equalto':
						case '==':
							return (eval(val)==eval(params.param2))?true:false
						break;
						case 'notequal':
						case '!=':
							return (eval(val)!=eval(params.param2))?true:false
						break;
					}
			break;
			case 'datetime':
				return val.match(/^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\/|-|\.|\x20)(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})(\/|-|\.|\x20)(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8])))) ([01]\d|2[0-3])(:[0-5]\d){0,2}$/);
			break;
			case 'date':
				return val.match(/^(?:(?:(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\/|-|\.|\x20)(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})(\/|-|\.|\x20)(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8]))))$/);
			break;
			case 'time':
				return val.match(/^([01]\d|2[0-3])(:[0-5]\d){0,2}$/);
			break;
			case 'boolean':
				return val.match(/^0|1$/);
			break;
			case 'decimal':
				return val.match(/^[-+]?[0-9]*\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/);
			break;
			case 'email':
				return this.validEmail(val);
			break;
			case 'equalTo':
				return (val==params.param1)?true:false
			break;
			case 'extension':
				return val.match(params.param1);
			break;
			case 'ip':
				return val.match(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/);
			break;
			case 'minLength':
				return (val.length<params.param1)?false:true
			break;
			case 'maxLength':
				return (val.length>params.param1)?false:true
			break;
			case 'length':
				return (val.length==params.param1);
			break;
			case 'numeric':
				return val.match(/^[-+]?[0-9]*\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/);
			break;
			case 'phone':
				return val.match(/^\+[0-9]{11}$/);
			break;
			case 'postal':
				return val.match(/^[0-9]{2}-[0-9]{3}$/);
			break;
			case 'range':
				if (isNaN(val))
					return false;
				return (( eval(val)>eval(params.param1)) && (eval(val)<eval(params.param2))) ? true:false
			break;
			case 'inList':
				return val.match(params.param1);
			break;
			case 'username':
				return val.match(/^[a-zA-Z0-9_]*$/);
			break;
			case 'alpha':
				return val.match(/^[a-zA-Z]*$/);
			break;
			case 'alphanumeric':
				return val.match(/^[a-zA-Z0-9]*$/);
			break;
			case 'int':
				return val.match(/^[0-9]+$/);
			break;
			case 'float':
				return val.match(/[0-9]+\.[0-9]+$|^[0-9]+$/);
			break;
			case 'tags':
				return val.match(/^[ ]*[\w ,]*[ ]*$/);
			break;
			case 'required':
				return val;
			break;
			case 'checked':
				return val
			break;
			case 'selected':
				return val
			break;
			case 'custom':
			case 'regex':
				return val.match(params.param1);
			break;			
			case 'url':
				return val.match(/^(?:(?:https?|ftps?|file|news|gopher):\/\/)?(?:(?:(?:25[0-5]|2[0-4]\d|(?:(?:1\d)?|[1-9]?)\d)\.){3}(?:25[0-5]|2[0-4]\d|(?:(?:1\d)?|[1-9]?)\d)|(?:[0-9a-z]{1}[0-9a-z\-]*\.)*(?:[0-9a-z]{1}[0-9a-z\-]{0,62})\.(?:[a-z]{2,6}|[a-z]{2}\.[a-z]{2,6})(?::[0-9]{1,4})?)(?:\/?|\/[\w\-\.,@?^=%&:;\/~\+#]*[\w\-\@?^=%&\/~\+#])$/i);
			break;			
			case 'uniqueUsername':
				return this.uniqueUsername(id, message);
			break;			
			case 'uniqueEmail':
				return this.uniqueEmail(id, message);
			break;			
			case 'confirmPassword':
				return this.confirmPassword(id);
			break;
			case 'password':
				return val.match(/^.*(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$/);
			break;
			default:
				try
				{
					eval("this.rule="+rule);
					return this.rule(id, params, message);
				}
				catch(err)
				{
				}
				return true;
			break;			
		}
	},
	
	validEmail: function(email)
	{
		if(email.length<=0)
		{
			return true;
		}
		var splitted=email.match("^(.+)@(.+)$");
		if (splitted==null)
			return false;
		if(splitted[1]!=null)
		{
			var regexp_user=/^\"?[\w-_\.]*\"?$/;
			if(splitted[1].match(regexp_user)==null)
				return false;
		}
		if(splitted[2]!=null)
		{
			var regexp_domain=/^[\w-\.]*\.[A-Za-z]{2,4}$/;
			if(splitted[2].match(regexp_domain)==null)
			{
			var regexp_ip=/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/;
			if(splitted[2].match(regexp_ip)==null)
				return false;
			}
			return true;
		}
		return false;
	},
	
	uniqueUsername: function(tag, message)
	{
		el=$("#"+tag);
		val=el.attr("value");
		
		if ((val) && (val!=this.usernameRequest))
		{
			this.usernameRequest=val;
			$.ajax({
				  url: this.ajaxRequestUrl+'/check_username/'+val+'/',
				  cache: false,
				  success: function(html){
						if (html.match("err"))
						{
							Validation.showMessage(tag, message)
							Validation.emailRequestResult=false;	
						}
						else
						{
							Validation.hideMessage(tag)
							Validation.emailRequestResult=true;	
						}				    
				  }
			});	
		}
		else
			return Validation.usernameRequestResult;	

		return true;
	},
	
	uniqueEmail: function(tag, message)
	{
		el=$("#"+tag);
		val=el.attr("value");
		
		if ((val) && (val!=this.emailRequest))
		{
			this.emailRequest=val;

			$.ajax({
				  url: this.ajaxRequestUrl+'/check_email/'+val+'/',
				  cache: false,
				  success: function(html){
						if (html.match("err"))
						{
							Validation.showMessage(tag, message)
							Validation.emailRequestResult=false;	
						}
						else
						{
							Validation.hideMessage(tag)
							Validation.emailRequestResult=true;	
						}				    
				  }
			});	
			
		}
		else
			return Validation.emailRequestResult;
			
		return true;		
	},
	
	confirmPassword: function(tag)
	{
		if (($("#"+tag).attr("value"))!=($("#"+this.modelName+"Password").attr("value")))
			return false;
		return true;
	},
	
	turnOff: function(tag, rule)
	{
		var it;
		for (it in this.formFields)
		{
			if (Validation.formFields[it][0])
			{
				if (Validation.formFields[it][0]["tag"])
				{
					for(var i=0; i<	Validation.formFields[it].length; i++)
					{
						if ((Validation.formFields[it][i]["tag"]==tag) && (Validation.formFields[it][i]["rule"]==rule))
							Validation.formFields[it][i]["doValidate"]=false;
					}
				}
			}
		}
	},	
	
	turnOn: function(tag, rule)
	{
		var it;
		for (it in this.formFields)
		{
			if (Validation.formFields[it][0])
			{
				if (Validation.formFields[it][0]["tag"])
				{
					for(var i=0; i<	Validation.formFields[it].length; i++)
					{
						if ((Validation.formFields[it][i]["tag"]==tag) && (Validation.formFields[it][i]["rule"]==rule))
							Validation.formFields[it][i]["doValidate"]=true;
					}
				}
			}
		}
	}	
};
