Validator = Class.create();
Validator.prototype = {
		f : null,
		objs : null,
		dynamic : false,		
		formErrorHandler : null,
		sendFunc : null,
		
		initialize : function(formName, dynamic)
		{
			this.f = $(document.getElementById(formName));
				
			if(dynamic) this.dynamic = true;
			
			if(!this.dynamic)
			{
				this.collectItems();
			}

			this.f.bind('submit', this.validate.bindAsEventListener(this));
		},
			
		collectItems : function()
		{
			this.objs = new Array();
			var els = $('[@validate]', this.f).get();
			for(i in els)
			{
				this.objs[this.objs.length] = new ValidatorItem(els[i]);
			}
		},
		
		validate : function()
		{
			if(this.dynamic)
			{
				this.collectItems();
			}
			
			var send = true;
			for(i in this.objs)
			{
				if(!this.objs[i].validate())
				{
					send = false;
				}
			}

			if(send)
			{
				if(this.sendFunc)
				{
					var res = this.sendFunc();
					if(res)
					{
						return true;
					}
					else
					{
						return false;
					}
				}
				return true;
			}
			else
			{
				if(this.formErrorHandler)
				{
					this.formErrorHandler();
				}
				return false;
			}						
		},
		
		setFormErrorHandler : function(func)
		{
			this.formErrorHandler = func;
		}
	};
	
ValidatorItem = Class.create();
ValidatorItem.prototype = {
	obj : null,
	t : '',
	error : false,
	instantCheck : false,
	
	initialize : function(obj, mode)
	{
		this.obj = $(obj);
		this.t= this.obj.attr('validate');
	},
	
	validate : function()
	{
//		if(this.instantCheck) return !this.error;
		return this._validate();
	},
	
	_validate : function()
	{
		var s = false;
		
		switch(this.t)
		{
			case 'userfunc' : 
			
				var params = this.obj.attr('validate_params');
				if(params)
				{
					var v = $.trim(this.obj.val());
					eval("s = " + params + "(v, this.obj);");
				}
			
			break;
			
			case 'email' : 
				
				var v = $.trim(this.obj.val());
				var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
				if (filter.test(v)) 
				{
					s = true;
				}
				else
				{
					s = false;
				}
											
			break; 
			
			case 'numeric':
				
				var v = $.trim(this.obj.val());
				
				s = v.match(/^\d+$/);
				
				var params = this.obj.attr('validate_params');
				if(params && s)
				{
					params = params.split(':');
					var r = {};
					r.from = parseInt(params[0], 10);
					r.to = parseInt(params[1], 10);
					r.from = isNaN(r.from) ? 0 : r.from;
					r.to = isNaN(r.to) ? 0 : r.to;
										
					s = this.validateRange($.trim(this.obj.val()), r);
				}
							
			break;
			
			case 'string':
			
				var params = this.obj.attr('validate_params');
				params = params.split(':');
				var r = {};
				r.from = parseInt(params[0], 10);
				r.to = parseInt(params[1], 10);
				r.from = isNaN(r.from) ? 0 : r.from;
				r.to = isNaN(r.to) ? 0 : r.to;
				s = this.validateRange($.trim(this.obj.val()).length, r);
				
			break;
			
			case 'equalto':
			
				var params = this.obj.attr('validate_params');
				s = (this.obj.val() == $('#' + params).val());
			
			break;
			
			case '1':
			case 'true':
			case 'default' : 
			case 'notblank':
				s = this.validateDefault($.trim(this.obj.val()).length);
			break;
		}
				
		
		if(s)
		{
			this.ok();
			return true;
		}
		else
		{	
			this.err();
			return false;
		}
	},
	
	validateDefault : function(v)
	{
		return (v ? true : false);
	},
	
	validateRange : function(v, r)
	{
		var s = false;
		if(r.from && r.to)
		{
			if(v >= r.from && v <= r.to)
			{
				s = true;
			}
			else
			{
				s = false;
			}
		}
		else if(r.from)
		{
			if(v >= r.from)
			{
				s = true;
			}
			else
			{
				s = false;
			}
		}
		else if(r.to)
		{
			if(v <= r.to)
			{
				s = true;
			}
			else
			{
				s = false;
			}
		}
		return s;
	},
	
	ok : function()
	{
		if(!this.instantCheck)
		{
			this.instantCheck = true;
			this.obj.keyup(this._validate.bindAsEventListener(this));
		}
		
		if(!this.error) return;
			
		this.error = false;
		this.obj.removeClass('error');
	},
	
	err : function()
	{
		if(this.error) return;
		
		if(!this.instantCheck)
		{
			this.instantCheck = true;
			this.obj.keyup(this._validate.bindAsEventListener(this));
		}
		
		this.error = true;		
		this.obj.addClass('error');
	}
};