Validator=Class.create();
Validator.Handle=Class.create();
Validator.Handle.prototype={
	_list:{'cnt':1,'items':new Array()},
	_states:{'isValid':true,'controlsInited':false},
	initialize:function(){},
	getNextID:function(){
		return ++this._list['cnt'];
	},
	getIsValid:function(){
		return this._states['isValid'];
	},
	setIsValid:function(param){
		this._states['isValid']=param;
	},
	getControlsIsInitiated:function(){
		return this._states['controlsInited'];
	},
	setControlsIsInitiated:function(param){
		this._states['controlsInited']=param;
	},
	visibleValidatorMessageByID:function(ValidatorID){
		$O(ValidatorID).style.display='';
		this.setIsValid(false);
	}
}
ValidatorHandle=new Validator.Handle();

/*
	params:
		*to:
		*type:
		*message:
		compareTo:
		regexp:
		function:
		minLength:
		maxLength:
		minValue:
		maxValue:
		cssClass:
		group:
		event:
		focusOnError:
	*:required param
*/
Validator.prototype={
	initialize:function(params){
		this._params=params;
		this._handle=ValidatorHandle;
		this.create();
	},
	create:function(){
		if(this._params['containerID']==undefined){
			this.createTextContainer();
		} else {
			this._params['validatorID']=this._params['containerID'];
			$O(this._params['validatorID']).innerHTML=this._params['message'];
			$O(this._params['validatorID']).style.display='none';
		}
		this._handle._list['items'].push(this._params);
	},
	createTextContainer:function(){
		if(this._params['view']=='block'){
			var container=$Ce('div');
		}
		else{
			var container=$Ce('span');
		}
		if(this._params['view']!='show'){
			container.style.display='none';
		}
		container.id='validator$'+this._params['to']+'$'+this._params['type']+'$'+this._handle.getNextID();
		container.innerHTML=' '+this._params['message'];
		if(this._params['cssClass']==undefined){
			container.className='color-warning';
		}
		$O(this._params['to']).parentNode.insertBefore(container,$O(this._params['to']).nextSibling);
		this._params['validatorID']=container.id;
	}
}

ValidatorEvent=Class.create();
ValidatorEvent.prototype={
	initialize:function(params){
		this._params=params;
		this._handle=ValidatorHandle;
		this.create();
	},
	create:function(){
		VateraEvent.add(this._params['to'],(this._params['event']==undefined)?'click':this._params['event'],this.validate,this);
		if (this._params['event']=='paste'){
			VateraEvent.add(this._params['to'],'input',this.validate,this); //To control paste in Firefox
		} else if (this._params['event']=='input'){
			VateraEvent.add(this._params['to'],'paste',this.validate,this); //To control paste in IE
		}
	},
	initControls:function(ValidatorInstance){
		var inputs=document.getElementsByTagName('input');
		var selects=document.getElementsByTagName('select');
		var textareas=document.getElementsByTagName('textarea');
		for(var i=0;i<inputs.length;i++){
			if(typeof inputs[i].id=='string'&&inputs[i].id!=ValidatorInstance._params['to']){
				VateraEvent.attachEvent(new VateraEventRecord(inputs[i],'click',ValidatorInstance.validate,ValidatorInstance));
				VateraEvent.attachEvent(new VateraEventRecord(inputs[i],'keyup',ValidatorInstance.validate,ValidatorInstance));
			}
		}
		for(i=0;i<selects.length;i++){
			if(typeof selects[i].id=='string'&&selects[i].id!=ValidatorInstance._params['to']){
				VateraEvent.attachEvent(new VateraEventRecord(selects[i],'change',ValidatorInstance.validate,ValidatorInstance));
			}
		}
		for(i=0;i<textareas.length;i++){
			if(typeof textareas[i].id=='string'&&textareas[i].id!=ValidatorInstance._params['to']){
				VateraEvent.attachEvent(new VateraEventRecord(textareas[i],'change',ValidatorInstance.validate,ValidatorInstance));
				VateraEvent.attachEvent(new VateraEventRecord(textareas[i],'blur',ValidatorInstance.validate,ValidatorInstance));
			}
		}
	},
	validate:function(Sender,Event,ValidatorInstance){
		if(!ValidatorInstance._handle.getControlsIsInitiated()){
			ValidatorInstance.initControls(ValidatorInstance);
			ValidatorInstance._handle.setControlsIsInitiated(true);
		}
		ValidatorInstance._handle.setIsValid(true);
		var items=ValidatorInstance._handle._list['items'];
		var ItemFocused=false;
		var notValidItems=new Array();
		for(var i=0;i<items.length;i++){
			if(
				ValidatorInstance._params['group']!=undefined&&
				items[i]['group']!=undefined&&
				items[i]['group']!=ValidatorInstance._params['group']
			){
				// if item group same
				continue;
			}
			ValidatorItemIsValid=true;
			
			// when items collection contains the validator, but validator not exists in DOM
			if($O(items[i]['validatorID'])==null){
				continue;
			}	
			$O(items[i]['validatorID']).style.display='none';
			switch(items[i]['type']){
				case 'required':
					if($Ov(items[i]['to'])==''){
						ValidatorItemIsValid=false;
					}
					break;
				case 'dataType':
					switch(items[i]['dataType']){
						case 'number':
							if(isNaN($Ov(items[i]['to']))){
								ValidatorItemIsValid=false;
							}
							break;
					}
					break;
				case 'compare':
					if($Ov(items[i]['to'])!=$Ov(items[i]['compareTo'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'regexp':
					if(!$Ov(items[i]['to']).match(items[i]['regexp'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'custom':
					if((typeof items[i]['function'])=='string'){
						if(!eval(items[i]['function']+'();')){
							ValidatorItemIsValid=false;
						}
					}
					else{
						if(!items[i]['function'](items[i])){
							ValidatorItemIsValid=false;
						}
					}
					break;
				case 'minLength':
					if($Ov(items[i]['to']).length<items[i]['minLength']){
						ValidatorItemIsValid=false;
					}
					break;
				case 'maxLength':
					if($Ov(items[i]['to']).length>items[i]['maxLength']){
						ValidatorItemIsValid=false;
					}
					break;
				case 'email':
					if(
						$Ov(items[i]['to']).match(/^[a-z0-9.\-_]+@([a-z0-9-_]{1,}.){0,8}[a-z0-9-_]{3,}.[a-z]{2,4}$/gi)==null&&
						$Ov(items[i]['to'])!=""
					){
						ValidatorItemIsValid=false;
					}
					break;
				case 'maximum':
					if(parseInt($Ov(items[i]['to']))>parseInt(items[i]['maxValue'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'minimum':
					if(parseInt($Ov(items[i]['to']))<parseInt(items[i]['minValue'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'between':
					if($Ov(items[i]['to'])=='' || parseInt($Ov(items[i]['to']))>parseInt(items[i]['maxValue']) || parseInt($Ov(items[i]['to']))<parseInt(items[i]['minValue'])){
						ValidatorItemIsValid=false;
					}
					break;
			}
			
			if($O(items[i]['to']).disabled){
				ValidatorItemIsValid=true;
			}
			
			if(!ValidatorItemIsValid){
				if(
					ItemFocused==false&&
					Sender.id==ValidatorInstance._params['to']&&
					items[i]['focusOnError']==true
				){
					$O(items[i]['to']).focus();
					ItemFocused=true;
				}
				ValidatorInstance._handle.visibleValidatorMessageByID(items[i]['validatorID']);
				notValidItems.push(items[i]['to']);
			}
		}
		
		if(ValidatorInstance._params['callback']!=undefined){
			eval(ValidatorInstance._params['callback']+'('+ValidatorInstance._handle.getIsValid()+');');
		}

		if(!ValidatorInstance._handle.getIsValid()){
			if(Sender.type=='checkbox'||Sender.type=='radio'||Sender.type=='file'){
				return false;
			}
			VateraEvent.stop(Event);
			return false;
		}
		if(ValidatorInstance._params['confirmText']!=undefined&&Sender.id==ValidatorInstance._params['to']){
			if(!confirm(ValidatorInstance._params['confirmText'])){
				VateraEvent.stop(Event);
				return false;
			}
		}
		return true;
	}
}