window.addEvent('domready', function(){
	var JFormValidator = new Class({
		initialize: function()
		{
			// Initialize variables
			this.handlers	= Object();
			this.custom		= Object();

			// Default handlers
			this.setHandler('username',
				function (value) {
					regex = new RegExp("[\<|\>|\"|\'|\%|\;|\(|\)|\&]", "i");
					return !regex.test(value);
				}
			);

			this.setHandler('password',
				function (value) {
					regex=/^\S[\S ]{2,98}\S$/;
					return regex.test(value);
				}
			);

			this.setHandler('numeric',
				function (value) {
					regex=/^(\d|-)?(\d|,)*\.?\d*$/;
					return regex.test(value);
				}
			);

			this.setHandler('email',
				function (value) {
					regex=/^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/;
					return regex.test(value);
				}
			);

			this.setHandler('phone',
				function (value) {
					value = value.replace(/[-\(\)\.+ ]/g,'');

					for (var i = 0;i<value.length;i++){
						if (((value.charAt(i) < "0") || (value.charAt(i) > "9"))) return false;
					}
	   			return true;
				}
			);

			this.setHandler('url',
				function (value) {
					regex = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
					return regex.test(value);
				}
			);


			// Attach to forms with class 'form-validate'
			var forms = $$('form.form-validate');
			forms.each(function(form){ this.attachToForm(form); }, this);
		},

		setHandler: function(name, fn, en)
		{
			en = (en == '') ? true : en;
			this.handlers[name] = { enabled: en, exec: fn };
		},

		attachToForm: function(form)
		{
			// Iterate through the form object and attach the validate method to all input fields.
			$A(form.elements).each(function(el){
				el = $(el);
				if ((el.getTag() == 'input' || el.getTag() == 'button') && el.getProperty('type') == 'submit') {
					if (el.hasClass('validate')) {
						el.onclick = function(){return document.formvalidator.isValid(this.form);};
					}
				} else {
					el.addEvent('blur', function(){return document.formvalidator.validate(this);});
				}
			});
		},

		validate: function(el)
		{
			// If the field is required make sure it has a value
			if ($(el).hasClass('required')) {
				if (!($(el).get('value'))) {
					this.handleResponse(false, el,false);
					return false;
				}
			}

			// Only validate the field if the validate class is set
			var handler = (el.className && el.className.search(/validate-([a-zA-Z0-9\_\-]+)/) != -1) ? el.className.match(/validate-([a-zA-Z0-9\_\-]+)/)[1] : "";
			if (handler == '') {
				this.handleResponse(true, el,false);
				return true;
			}

			// Check the additional validation types
			if ((handler) && (handler != 'none') && (this.handlers[handler]) && $(el).get('value')) {
				// Execute the validation handler and return result
				if (this.handlers[handler].exec($(el).get('value')) != true) {
					this.handleResponse(false, el,false);
					return false;
				}
			}

			// Return validation state
			this.handleResponse(true, el,false);
			return true;
		},

		validateGroup: function(groupID){
			var groupElements = $$('.validate-group-'+groupID);
			var groupValid = false;
			var someElementHasValue = false;
			var tthis = this;
			groupElements.each(function(el, index){
	  		if (($(el).get('value'))) {
					var handler = (el.className && el.className.search(/validate-([a-zA-Z0-9\_\-]+)/) != -1) ? el.className.match(/validate-([a-zA-Z0-9\_\-]+)/)[1] : "";
					if ((handler) && (handler != 'none') && (tthis.handlers[handler]) && $(el).get('value')) {
						// Execute the validation handler
						if (tthis.handlers[handler].exec($(el).get('value')) == true) {
							groupValid = true;
						}
					}
					someElementHasValue = true;
				}
	  	});
			if (!someElementHasValue)
				groupValid = false;
			//now we know if whole group is valid and we can apply the result to the group elements
			groupElements.each(function(el, index){
				tthis.handleResponse(groupValid, el,groupID);
			});
			return groupValid;
		},

		isValid: function(form){
			var valid = true;
			var validationGroups = new Array();
			// Validate form fields
			for (var i=0;i < form.elements.length; i++) {
				//Special Validation for Validation Groups
				var classString = "";

				if (Browser.Engine.trident){
					var valObjName = form.elements[i].name;
					classString = $$(valObjName).get('class');
				}
				else
					classString = form.elements[i].get('class');

				if (classString.contains('validate-group-')) {
					var classStringSplit = classString.split(' ');
					var validationGroup;
					for (var j = 0; j< classStringSplit.length;j++){
						if (classStringSplit[j].contains('validate-group-'))
							validationGroup = classStringSplit[j].substring(15).toInt();
					}
					if(!validationGroups.contains(validationGroup)){
						validationGroups.push(validationGroup);
					}
				}
				else {
					if (this.validate(form.elements[i]) == false) {
						valid = false;
					}
				}
			}
			//Scpecial Validation for now collected Validation Groups
			var tthis = this;
			validationGroups.each(function(validationGroup, index){
				var groupValid = tthis.validateGroup(validationGroup);
				if (!groupValid)
					valid = false;
			});


			// Run custom form validators if present
			if ($(this.custom)){
				$(this.custom).each(function(validator){
					if (validator.exec() != true) {
						valid = false;
					}
				});
			}

			return valid;
		},

		handleResponse: function(state, el, validationGroup)
		{
			// Find the label object for the given field if it exists
			if (!(el.labelref)) {
				var labels = $$('label');
				labels.each(function(label){
					if (label.getProperty('for') == el.getProperty('id')) {
						el.labelref = label;
					}
				});
			}

			// Set the element and its label (if exists) invalid state
			if (state == false) {
				el.addClass('invalid');
				if(!$(el.id + '_errorbox') && el.get('title')) {
					var errorbox  = new Element('span', {id: el.id + '_errorbox',text:el.get('title')});
					if (!Browser.Engine.trident)
						errorbox.setStyle('margin-top',el.getSize().y+1);
					errorbox.setStyle('width',el.getSize().x-8);
					errorbox.addClass('errorbox');
					errorbox.inject(el,'after');
				}
				if (el.getParent().hasClass('input'))
					el.getParent().addClass('invalid');
				if (el.labelref) {
					$(el.labelref).addClass('invalid');
				}
				el.removeEvents('change');
				if (validationGroup) // is the element part of a validation group?
					el.addEvent('change', function(){document.formvalidator.validateGroup(validationGroup)});
				else // normal validation
					el.addEvent('change', function(){document.formvalidator.validate(el)});
				if (errorbox){
					el.addEvent('mouseenter',
						function(){
							errorbox.setStyle('display','block');
						}
					);
					el.addEvent('mouseleave',
						function(){
							errorbox.setStyle('display','none');
						}
					);
				}
			} else {
				el.removeClass('invalid');
				if (!validationGroup) // is the element part of a validation group?
					el.removeEvents('change');
				if (el.getParent().hasClass('input'))
					el.getParent().removeClass('invalid');
				if (el.labelref) {
					$(el.labelref).removeClass('invalid');
				}
				if($(el.id + '_errorbox')) {
					$(el.id + '_errorbox').destroy();
				}
			}
		}
	});
	document.formvalidator = new JFormValidator();
});