/**
 * @author maxime
 */
if (!Edge) var Edge = {};
Edge.Validator = Class.create();
Edge.Validator.prototype = {
	
	initialize: function(form, rules, messages, options) {
		this.form = $(form) || Edge.Tools.Debug.error("You need to pass in a form as 1st parameter");
		this.rules = $H(rules) || Edge.Tools.Debug.error("No rules were defined");
		var messages = messages || Edge.Tools.Debug.error("No error messages were defined");
		
		this.submitter = this.form.getElementsBySelector('input[name=submitButton]')[0] || Edge.Tools.Debug.error("Could'nt find elm with name 'submitButton'");
		var resetter = this.form.getElementsBySelector('input[name=resetButton]')[0] || null;	
		
		this.submitEL = this.validate.bind(this);
		this.errFieldEL = this.hideError.bind(this);
		
		if (options) {
			if (options.overrideSubmitter) this.submitMethod = options.overrideSubmitter;
		}
		
		this.submitter.observe('click', this.submitEL);
		if (resetter) resetter.observe('click', this.reset.bind(this));
		
		this.rules.each(function(rule) {
			var field = $(rule.key);			
			if (!field) field = this.form.getElementsBySelector('input[name='+rule.key+']')[0];
			var rule = rule.value;

			field.ftype = field.tagName.toLowerCase() == 'input' ? field.type : field.tagName.toLowerCase();	
			field.validate = function() {
				var msg; var msg2; 
				if (rule.required && (!field.value || field.value == 0 || 
					((field.ftype == 'radio' || field.ftype == 'checkbox') && !this.groupIsSelected(field)))) {
					msg = messages.required[field.ftype];
					if (field.ftype == 'password' && !$F(field.id+'2')) msg2 = messages.required['password'];
				}
				if (!msg && rule.min && field.value.length < rule.min) 
					msg = field.ftype == 'password' ? messages.pwd.invalid : messages.format.min;
				if (!msg && rule.format && field.value.length && !this['isValid' + rule.format[0].capitalize()](field.value, rule.format[1])) 
					msg = messages.format[rule.format[0]];
				if (!msg && field.ftype == 'password' && $(field.id+'2') && field.value != $F(field.id+'2')) 
					msg = msg2 = messages.pwd.unequal;
					
				if (msg) this.showError(field, msg, rule.align);
				if (msg2) this.showError($(field.id+'2'), msg2, rule.align);
			}.bind(this);
		}.bind(this));	//1.5
	},
	
	validate: function(event) {
		Event.stop(event);	//1.5
		this.form.getInputs().concat($A(this.form.getElementsByTagName('select'))).each(function(input) {
			if (input.validate) input.validate();
		});
		var errors = this.form.getElementsByClassName('validation-error');
		errors.length ? errors[0].scrollTo() : this.submit();		
	},
	
	submit: function() {
		//CF HACK! with js submission the image buttons seem to disappear from the form scope, so we insert a hidden field with the same name
		new Insertion.Top(this.form, '<input type="hidden" name="'+this.submitter.name+'" value="dummy" />');	//1.5
		this.submitMethod ? this.submitMethod() : this.form.submit();
	},
	
	showError: function(field, errMsg, align) {
		if (field.tt) field.tt.msg = errMsg;
		else field.tt = new Edge.Tooltip(field, errMsg, {
			align : align,
			dropShadow : true,
			style : 'validation-message',
			shadowStyle : 'validation-shadow'
		});
		field.tt.show();
		field.addClassName('validation-error');
		
		switch (field.ftype) {
			case 'text': case 'textarea': case 'password': case 'file': 	
							field.observe('keyup', this.errFieldEL); break;
			case 'checkbox': case 'radio': 	
							var options = this.form.getElementsBySelector('input[name='+field.name+']');
							for (var e in options) Event.observe(options[e], 'click', this.errFieldEL);
							break;
			case 'select':	field.observe('change', this.errFieldEL); break;
			default: 		field.observe('keyup', this.errFieldEL);
		}	
	},
	
	hideError: function(event) {
		var trigger = Event.element(event); //1.5
		if (trigger.tagName.toLowerCase() == 'button')
			trigger = $(trigger.id.substr(7, trigger.id.length-7));
		if (trigger.tagName.toLowerCase() == 'option') 
			while (trigger.tagName.toLowerCase() != 'select') {
				trigger = trigger.up(0);
			}
		if (trigger.type == 'radio') trigger = this.form.getElementsBySelector('input[name='+trigger.name+']');
		if (trigger.type == 'password') trigger = this.form.getElementsBySelector('input[type=password]');
		if (!(trigger instanceof Array)) trigger = [trigger];
		
		trigger.each(function(trigger) {
			trigger.removeClassName('validation-error');
			if (trigger.tt) trigger.tt.hide();
			trigger.stopObserving(this.errFieldEL);
		});
	},
	
	groupIsSelected: function(field) {
		var options = this.form.getElementsBySelector('input[name='+field.name+']');
		for (var e in options) if (options[e].checked) return true;
		return false;
	},
	
	reset: function(event) {
		Event.stop(event);
		this.form.reset(); 
		this.form.scrollTo();
	},
	
	isValidEmail: function(string) {
		return /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i.test(string);
	},
	
	isValidDate: function(string, format) {
		if (!string) return true;
		
		var regex = "^" + format.replace(/\w/ig, "\\d") + "$"; 
		if (new RegExp(regex, 'ig').test(string)) {
			if (format == "dd/mm/yyyy") {
				var dateParts = string.split("/");
				if (dateParts[0] < 1 || dateParts[0] > 31) return false;
				if (dateParts[1] < 1 || dateParts[1] > 12) return false;
				if (dateParts[2] < 1900) return false;
				return true;
			}			
		}
		return false;
	},
	
	isValidPhone: function(string, regex) {
		return (new RegExp(regex, 'ig').test(string));
	},
	
	isValidZip: function(string) {
		return string ? true : false;
	}
	
}