Validator = Class.create();

Validator.prototype = {
	initialize : function(className, error, test) {
		this.test = test ? test : function(){ return true };
		this.error = error ? error : 'Falló la Validación.';
		this.className = className;
	}
}

var Validation = Class.create();

Validation.prototype = {
	initialize : function(form, options){
		this.options = Object.extend({stopOnFirst : true}, options || {});
		this.form = $(form);
		Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
	},
	onSubmit :  function(ev){
		if(!this.validate()) Event.stop(ev);
	},
	validate : function() {
		if(this.options.stopOnFirst) {
			return Form.getElements(this.form).all($V);
		} else {
			var test = Form.getElements(this.form).collect($V);
			return test.all();
		}
	}
}

Object.extend(Validation, {
	validate : function(elm, index, options){ // index is here only because we use this function in Enumerations
		var options = Object.extend({}, options || {}); // options still under development and here as a placeholder only
		elm = $(elm);
		var cn = elm.classNames();
		return result = cn.all(Validation.test.bind(elm));
	},
	test : function(name) {
		var v = $VG(name);
		var id = 'advice-' + name + '-' + this.id;
		var prop = '__advice'+name;
		if(!v.test($F(this))) {
			if(!this[prop]) {
				var advice = document.createElement('div');
				advice.appendChild(document.createTextNode(v.error));
				advice.className = 'validation-advice';
				advice.id = id;
				advice.style.display = 'none';
				this.parentNode.insertBefore(advice, this.nextSibling);
				if(typeof Effect == 'undefined') {
					advice.style.display = 'block';
				} else {
					new Effect.Appear(advice.id, {duration : 1 });
				}
			}
			this[prop] = true;
			this.removeClassName('validation-passed');
			this.addClassName('validation-failed');
			return false;
		} else {
			try {
				$(id).remove();
			} catch(e) {}
			this[prop] = '';
			this.removeClassName('validation-failed');
			this.addClassName('validation-passed');
			return true;
		}
	},
	add : function(className, error, test, options) {
		var nv = {}
		nv[className] = new Validator(className, error, test, options);
		Object.extend(Validation.methods, nv);
	},
	get : function(name) {
		return  Validation.methods[name] ? Validation.methods[name] : new Validator();
	},
	methods : {}
});

var $V = Validation.validate;
var $VG = Validation.get;
var $VA = Validation.add;

$VA('IsEmpty', '', function(v) {
				return  ((v == null) || (v.length == 0) || /^\s+$/.test(v));
			});
$VA('required', 'Debe llenar este campo.', function(v) {
				return !$VG('IsEmpty').test(v);
			});
$VA('validate-number', 'Por favor, debe usar solo numeros en este campo.', function(v) {
				return $VG('IsEmpty').test(v) || !isNaN(v);
			});
$VA('validate-digits', 'Por favor, debe usar solo numeros en este campo.', function(v) {
				return $VG('IsEmpty').test(v) ||  !/[^\d]/.test(v);
			});
$VA('validate-alpha', 'Por favor, debe usar solo letras (a-z) en este campo.', function (v) {
				return /^[a-zA-Z ]+$/.test(v);
			});
$VA('validate-alpha-sines', 'Por favor, debe usar solo letras (a-z) en este campo.', function (v) {
				return $VG('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v);
			});
$VA('validate-alphanum', 'Por favor, debe usar solo letras (a-z) o numeros (0-9) en este campo. No se permite espacios.', function(v) {
				return $VG('IsEmpty').test(v) ||  !/\W/.test(v)
			});
$VA('validate-caractesp', 'Por favor, No colocar caracteres especiales.', function(v) {
				return $VG('IsEmpty').test(v) || v.indexOf("@") == "-1" && v.indexOf("<") == "-1" && v.indexOf(">") == "-1" && v.indexOf("&") == "-1" && v.indexOf("/") == "-1"  && v.indexOf("\\") == "-1" && v.indexOf("?") == "-1" && v.indexOf("¿") == "-1" && v.indexOf("-") == "-1" && v.indexOf("+");
			});
$VA('validate-date', 'Por favor, coloque una fecha valida.', function(v) {
				var test = new Date(v);
				return $VG('IsEmpty').test(v) || !isNaN(test);
			});
$VA('validate-email', 'Por favor, coloque un correo valido. Por ejemplo fred@domain.com.', function (v) {
				return $VG('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v);
			});
$VA('validate-phone', 'Por favor, coloque un telefono valido. Por ejemplo 0212-5555555 o +584125555555', function (v){
				//return $VG('IsEmpty').test(v) || /^[0-9]{2,3}-? ?[0-9]{6,7}$/.test(v);
				return $VG('IsEmpty').test(v) || /^[0-9]{4}[-]{1}[0-9]{7}$/.test(v) || /^[+]{1}[0-9]{12,15}$/.test(v);
			});
$VA('validate-ci', 'Por favor, coloque una cedula valida. Por ejemplo V-18458896 o E-89564568', function (v){
				//return $VG('IsEmpty').test(v) || /^[0-9]{2,3}-? ?[0-9]{6,7}$/.test(v);
				return $VG('IsEmpty').test(v) || /^[V,E,P,J]{1}[-]{1}[0-9]{8,10}$/.test(v);
			});
$VA('validate-tarjeta-credito', 'Por favor, coloque un numero de tarjeta de credito valido.', function (v){
				//return $VG('IsEmpty').test(v) || /^[0-9]{2,3}-? ?[0-9]{6,7}$/.test(v);
				return $VG('IsEmpty').test(v) || /^((67\d{2})|(4\d{3})|(5[1-5]\d{2})|(6011))(-?\s?\d{4}){3}|(3[4,7])\ d{2}-?\s?\d{6}-?\s?\d{5}$/.test(v);
			});
$VA('validate-date-au', 'Por favor usar un formato de fecha: dd/mm/yyyy. Por ejemplo 17/03/2006.', function(v) {
				if(!$VG('IsEmpty').test(v)) {
					var upper = 31;
					if(/^(\d{2})\/(\d{2})\/(\d{4})$/.test(v)) { // dd/mm/yyy
						if(RegExp.$2 == '02') upper = 29;
						if((RegExp.$1 <= upper) && (RegExp.$2 <= 12)) {
							return true;
						} else {
							return false;
						}
					} else {
						return false;
					}
				} else {
					return true;
				}
			});
$VA('validate-dollar', 'Por favor, colocar montos en $. Por ejemplo $100.00 .', function(v) {
				// [$]1[##][,###]+[.##]
				// [$]1###+[.##]
				// [$]0.##
				// [$].##
				return $VG('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
			});
/*
$VA('IsEmpty', '', function(v) {
				return  ((v == null) || (v.length == 0) || /^\s+$/.test(v));
			});
$VA('required', '	This is a required field.', function(v) {
				return !$VG('IsEmpty').test(v);
			});
$VA('validate-number', 'Please enter a valid number in this field.', function(v) {
				return $VG('IsEmpty').test(v) || !isNaN(v);
			});
$VA('validate-digits', 'Please use numbers only in this field.', function(v) {
				return $VG('IsEmpty').test(v) ||  !/[^\d]/.test(v);
			});
$VA('validate-alpha', 'Please use letters only in this field.', function (v) {
				return $VG('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v)
			});
$VA('validate-alphanum', 'Please use only letters or numbers.', function(v) {
				return $VG('IsEmpty').test(v) ||  !/\W/.test(v)
			});
$VA('validate-date', 'Please enter a valid date.', function(v) {
				var test = new Date(v);
				return $VG('IsEmpty').test(v) || !isNaN(test);
			});
$VA('validate-email', 'Please enter a valid email address.', function (v) {
				return $VG('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
			});
$VA('validate-date-au', 'Please use this date format: dd/mm/yyyy.', function(v) {
				if(!$VG('IsEmpty').test(v)) {
					var upper = 31;
					if(/^(\d{2})\/(\d{2})\/(\d{4})$/.test(v)) { // dd/mm/yyy
						if(RegExp.$2 == '02') upper = 29;
						if((RegExp.$1 <= upper) && (RegExp.$2 <= 12)) {
							return true;
						} else {
							return false;
						}
					} else {
						return false;
					}
				} else {
					return true;
				}
			});
$VA('validate-dollar', 'Please enter a valid $ amount.', function(v) {
				// [$]1[##][,###]+[.##]
				// [$]1###+[.##]
				// [$]0.##
				// [$].##
				return $VG('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
			});

*/
