var iRules = {
	name:{
		regex: /^.{3,128}$/,
		msg: 'Puede contener sólo números, letras y espacios.'
	},
	title:{
		regex: /^.{3,128}$/,
		msg: 'Puede contener números y letras.'
	},
	mail:{
		regex: /^([\w\d_\.\-])+\@(([\w\dáéíóúñ\-])+\.)+([\w\d]{2,4})+$/,
		msg: 'Ejemplo: usuario@dominio.com'
	},
	password:{
		regex: /^[\w\d]{3,18}$/,
		msg: 'Debe contener sólo números y letras.'
	},
	telephone:{
		regex: /^[\d()+\- ]{7,24}$/,
		msg: 'Ejemplos: 425-2354 , 051(511) +01 254 25402'
	},
	number:{
		regex: /^\d+$/,
		msg: 'Debe contener sólo numeros.'
	},
	character:{
		regex: /^[\w\d]$/,
		msg: 'Coincide con un caracter.'
	},
	content:{
		regex: /^(\s|.){3,}$/,
		msg: 'Mínimo 3 caracteres.'
	},
	date:{
		regex: /^[\wáé]{3,12} [\d]{1,3} [\w]{3,12} de [\d]{4}$/,
		msg: 'Ejemplo: Martes 06 Febrero de 2001'
	},
	hour:{
		regex: /^([0-9]|[0-1][0-9]|2[0-3]):[0-5]0$/,
		msg: 'Sólo intervalos de 10 minutos.<br /><b>Ejemplos</b>: 16:20, 00:40, 8:50, 13:00'
	},
	bool:{
		regex: /^0|1$/,
		msg: 'Debe elegir una de las opciones.'
	},
	image:{
		regex: /\.(jpg|jpeg|gif|png)$/i,
		msg: 'Debe elegir archivos de tipo imagen.'
	},
	multiple:{
		regex: /^\d+$/,
		msg: 'Debe agregar una o más opciones.'
	},
	multiple2:{
		regex: /^\d+$/,
		msg: 'Debe agregar una o más opciones.'
	}
};

var iValidator = new Class({
	Implements: Options,

	options:{
		focus: 'focus',
		valid: 'valid',
		invalid: 'invalid',
		norequired: 'norequired',
		blink: 'blink',
		maxlength: true
	},

	initialize: function(inputs,options){
		this.setOptions(options);
		this.inputs = inputs ;
		for(var i=0;i<this.inputs.length;i++){
			this.inputs[i].addEvents({focus:this.focus.bind(this),blur:this.blur.bind(this)});
			if(this.options.maxlength && this.inputs[i].getAttribute('maxlength') && this.inputs[i].getTag()=='textarea'){
				this.inputs[i].addEvent('keyup',function(){
					var maxlength = this.getAttribute('maxlength').toInt();
					if(this.value.length > maxlength){
						this.value = this.value.substr(0,maxlength);
					}
				});
			}
		}
	},

	focus: function(e){
		if(!this.disabled){
			this.stopBlink();
			this.hideTip();
			new Event(e).target.getParent().
			removeClass(this.options.blink).
			removeClass(this.options.valid).
			removeClass(this.options.invalid).
			addClass(this.options.focus);
		}
	},

	blur: function(e){
		if(!this.disabled){
			var input = new Event(e).target;
			var ruleName = input.className.split(' ')[0];
			var parent = input.getParent().
			removeClass(this.options.blink).
			removeClass(this.options.focus).
			removeClass(this.options.valid).
			removeClass(this.options.invalid);
			if(input.getAttribute('multiple')){
				if(ruleName=='multiple2'){
					if(input.options.length==0){
						parent.addClass(this.options.invalid);
					}else{
						parent.addClass(this.options.valid);
					}
				}
			}else{
				parent.addClass((input.value=='' && input.hasClass(this.options.norequired)) || input.value.test(iRules[ruleName].regex) ? this.options.valid : this.options.invalid);
			}
			this.stopBlink();
			this.hideTip();
		}
	},

	test: function(background){
		if(!this.disabled){
			this.status = true;
			this.errors = {};
			this.stopBlink();
			this.hideTip();
			for(var i=0;i<this.inputs.length;i++){
				var parent = this.inputs[i].getParent();
				if(!background){
					parent.
					removeClass(this.options.blink).
					removeClass(this.options.valid).
					removeClass(this.options.invalid).
					removeClass(this.options.focus);
				}
				var ruleName = this.inputs[i].className.split(' ')[0];
				var rule = iRules[ruleName];
				/*if(this.inputs[i].getAttribute('multiple')){
					if(ruleName=='multiple2'){
						if(this.inputs[i].options.length==0){
							parent.addClass(this.options.invalid);
							this.errors[this.inputs[i].name] = rule.msg;
							this.status=false;
						}else{
							parent.addClass(this.options.valid);
						}
					}
				}else{*/
					if((this.inputs[i].getProperty('invalid') && this.inputs[i].getProperty('invalid')=='1') || (this.inputs[i].value!='' || !this.inputs[i].hasClass(this.options.norequired)) && !this.inputs[i].value.test(rule.regex)){
						if(!background){
							parent.addClass(this.options.invalid);
						}
						this.status=false;
						if(this.inputs[i].getTag()=='select' && !this.inputs[i].getAttribute('multiple')){
							this.errors[this.inputs[i].name] = 'Debe seleccionar una de las opciones.';
						}else{
							this.errors[this.inputs[i].name] = rule.msg;
						}
					}else if(!background){
						parent.addClass(this.options.valid);
					}
				//}
			}
			return this.status;
		}else{
			return null;
		}
	},

	showInvalid: function(blink,tip,showName){
		if(blink!=true){ blink=false; }
		if(tip!=true && $type(tip)!='object'){ tip=false; }
		for(var i=0;i<this.inputs.length;i++){
			if(this.inputs[i].getParent().hasClass(this.options.invalid)){
				this.inputs[i].getParent().
				removeClass(this.options.blink).
				removeClass(this.options.focus).
				removeClass(this.options.valid).
				removeClass(this.options.invalid);
				if(blink || tip){
					//parpadeo
					if(blink){
						this.inputs[i].getParent().addClass(this.options.blink);
						this.blinker={
							index: i,
							timer: this.inputs[i].getParent().toggleClass.periodical(250,this.inputs[i].getParent(),[this.options.blink])
						};
					}
					//tip
					if(tip){
						this.showTip(this.inputs[i],tip,showName);
					}
				}else{
					this.inputs[i].focus();
				}
				break;
			}
		}
	},
	
	showTip: function(input,pos,showName){
		pos = $merge({x:-230,y:-24},pos);
		if(input.getTag()=='select' && !input.getAttribute('multiple')){
			var msg = 'Debe seleccionar una de las opciones.';
		}else{
			var msg = iRules[input.className.split(' ')[0]].msg;
		}
		if(!$defined(showName) || showName==true){
			var title = '<h3>'+input.name.capitalize()+'</h3>';
		}else if(showName==false){
			var title = '';
		}else{
			var title = '<h3>'+(showName==true ? input.name.capitalize() : showName)+'</h3>';
		}
		//
		this.tip = new Element('div',{'class':'iVtip'}).setOpacity(0).setHTML('<div>'+title+'<p>'+msg+'</p></div><div class="foot"></div>').inject(document.body);
		var position = input.getPosition();
		this.tip.setStyles({'left':(position.x+pos.x)+'px','top':(position.y+pos.y)+'px'});
		new Fx.Tween(this.tip,'opacity').start(1);
	},

	hideTip: function(){
		if(this.tip){
			this.tip.remove();
			this.tip = false;
		}
	},

	stopBlink: function(){
		if(this.blinker){
			$clear(this.blinker.timer);
			this.inputs[this.blinker.index].getParent().removeClass(this.options.blink);
			delete this.blinker;
		}
	},
	
	displayErrors: function(box,extra){
		var error = '';
		for(var i in this.errors){
			error += '- '+i.capitalize()+': '+this.errors[i]+'\n';
		}
		if(error!=''){
			var errors = this.errors;
			if(extra){
				errors = $merge(errors,extra);
			}
			if(box){
				box.empty();
				new Element('h3').setText('Debe corregir los datos de los siguientes campos:').inject(box);
				var list = new Element('ul').inject(box);
				for(var i in errors){
					new Element('li').setHTML('<b>'+i.capitalize()+'</b>: '+errors[i]).inject(list);
				}
			}else{
				alert('Debe corregir los datos de los siguientes campos:\n\n'+error);
			}
		}
	}

});
