﻿/*
 * CustomField class
 */

var CustomField = Class.create();
CustomField.prototype = {
  initialize: function(name, value, classnames, type) {
    this.name = name;
    this.value = value;
    this.classnames = classnames;
    this.type = type;
  }
};

/*
 * Validation class 
 */

var Validation = Class.create();
Validation.prototype = {
	initialize : function(form, validatorAPI, options) {
		this.options = Object.extend(
			{onFormValidate : function(result, form) {}, showAdvice : true, markFields : true, submitOnSucess:true}, 
			options || {}
		);
		this.form = $(form);
		this.validatorAPI = validatorAPI;
		
		Event.observe(this.form, 'submit' , this.onSubmit.bind(this), false);
	},
	
	onSubmit : function(ev) {
		if (ev != null) Event.stop(ev);
		this.validate(); 
	},
	
	validate : function() {
		this.reset();

		var customFields = new Array();
		var inputs = this.form.getElements();
		inputs.each(function(input, index) {
			var classNames = $w(input.className);
			var name = Validation.getElmID(input);
			var type = input.type.toLowerCase();
			
			// todo refactor
			var value = input.value;
			if (type == 'radio') {
				value = input.checked ? value : '';
			}
			
			var customField = new CustomField(name, value, classNames, type);
			this.push(customField);
		}, customFields);
					
	  	var myAjax = new Ajax.Request(this.validatorAPI, {
	      	method:'post', postBody:"customFields=" + customFields.toJSON(),
	      	onSuccess: this.onFormValidated.bind(this)
	  	});
	},
	
	onFormValidated : function (transport) {
		var errors = (transport.responseText).evalJSON(true);
		
		if(errors == null) {
			// submit form if there are no validation errors
			if(this.options.submitOnSuccess) this.form.submit();
		} else { // show validation errors
			errors.each(function(error) {
				elm = this.getElm(this.form, error.name);
				Validation.markAsFailed(elm, error.value, this.options);
			}.bind(this));
		
			if (!this.options.showAdvice) {
				alert("Bitte vervollständigen Sie Ihre Eingaben.");
			}
		}
		
		// callback function to execute after validation
		this.options.onFormValidate(errors, this.form);
	},
	
	reset : function() {
		Form.getElements(this.form).each(function(elm) {
			var advice = Validation.getAdvice(elm);
			if (advice != null) advice.remove();
			elm.removeClassName('validation-failed');
		});
	},
	
	getElm :  function (form, nameOrId) {
		var element = $(nameOrId);
		if (element == null) {
			Form.getElements(form).each(function(elm) {
				if (elm.id == nameOrId || elm.name == nameOrId) element = elm;
			});
		}
		
		return element;
	}
}

Object.extend(Validation, {
	markAsFailed : function(elm, errorMsg, options) {
		var advice = Validation.getAdvice(elm);
		var utf8ErrorMsg = decodeURIComponent(escape(errorMsg));
		
		// show advice
		if(advice == null && options.showAdvice) {
			advice = Validation.createAdvice(elm, utf8ErrorMsg);
		}

		// mark field
		if (options.markFields) {
			elm.addClassName('validation-failed');
		}
	},
	
	createAdvice : function(elm, errorMsg) { 
		advice = '<div class="validation-advice" id="advice-' + Validation.getElmID(elm) +'">' + errorMsg + '</div>';
		
		switch (elm.type.toLowerCase()) {
			case 'checkbox': case 'radio':
				var p = elm.parentNode;
				if(p) {
					new Insertion.Bottom(p, advice);
				} else {
					new Insertion.After(elm, advice);
				}
				break;
			default:
				new Insertion.After(elm, advice);
		}
    },
	
	getAdvice : function(elm) {
		return $('advice-' + Validation.getElmID(elm));
	},
	
	getElmID : function(elm) {
		switch (elm.type.toLowerCase()) {
			case 'checkbox': case 'radio':
				// since checkbox and radio controls are grouped by its names
				return elm.name;
			default:
				return elm.id ? elm.id : elm.name;
		}
	}	
});