var Validator = Class.create(
	{
	
		initialize: function(formId, elements)
		{
			this._setForm(formId);
			this._addElements(elements);
			this._setElements();
			this.highlightErrors = false;
			this.highlightClass = 'highlighted';
			this.showErrors = false;
		},
		
		setHighlightErrors: function(trueOrFalse)
		{
			this.highlightErrors = trueOrFalse;
			return this;
		},
		
		getHighlightErrors: function()
		{
			return this.highlightErrors;
		},
		
		setHighlightClass: function(className)
		{
			this.highlightClass = className;
			return this;
		},
		
		getHighlightClass: function()
		{
			return this.highlightClass;
		},
		
		setShowErrors: function(trueOrFalse)
		{
			this.showErrors = trueOrFalse;
			return this;
		},
		
		getShowErrors: function()
		{
			return this.showErrors;
		},
		
		_setForm: function(formId)
		{
			this.form = $(formId);
			this.formId = formId;
			return this;
		},
		
		getForm: function()
		{
			return this.form;
		},
		
		getFormId: function()
		{
			return this.formId;
		},
		
		getElementsCounts: function()
		{
			return this.elementsCounts;
		},
		
		getElementsObjects: function()
		{
			return this.elementsObjects;
		},

		getElementsErrors: function()
		{
			return this.elementsErrors;
		},
		
		_addElements: function(elements)
		{
			if (elements instanceof Array) {
				$A(elements).each(
					function(element)
					{
						$(element).addClassName('required');
					}
				);
			}
			return this;
		},
		
		_setElements: function()
		{
			var elementsCounts = new Hash();
			var elementsObjects = new Hash();
			var elementsErrors = new Hash();
			this.getForm().getElements().each(
					function(element)
					{
						var count = elementsCounts.get(element.name);
						if (count == undefined) {
							count = 1;
						} else {
							count += 1;
						}
						elementsCounts.set(element.name, count);
						elementsObjects.set(element.name, element);
						elementsErrors.set(element.name, false);
					}
			);
			this.elementsCounts = elementsCounts;
			this.elementsObjects = elementsObjects;
			this.elementsErrors = elementsErrors;
			
			return this;
		},
		
		_validateEmpty: function(element)
		{
			
			if (element.value.length > 0) {
				if (element.hasClassName('email')) {
					return this._validateEmail(element);
				} else {
					return true;
				}
			} else {
				return false;
			}
		},
		
		_validateChecked: function(element, count)
		{
			
			var checked = 0;
			
			if (count > 1) {
				var elements = document.getElementsByName(element.name);
				for (e = 0; e < elements.length; e++) {
					if (elements[e].checked) {
						checked++;
					}
				}
			} else {
				if (element.checked) {
					checked++;
				} 
			}

			if (checked) {
				return true;
			} else {
				return false;
			}
			
		},
		
		_validateSelected: function(element)
		{
			if (element.selctedIndex != -1) {
				return this._validateEmpty(element);
			} else {
				return false;
			}
		},
		
		_validateEmail: function(element)
		{
			var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
			var address = element.value;
			return reg.test(address); 
		},
		
		validateElement: function(elementName)
		{
			var count = this.getElementsCounts().get(elementName);
			var element = this.getElementsObjects().get(elementName);
			
			var _this = this;
			
			var result;
			
			if (element.hasClassName('required')) {
				
				if (element.type == 'text' || element.type == 'password' || element.type == 'textarea' || element.type == 'hidden') {
					
					result = _this._validateEmpty(element);
					if (result) {
						_this.getElementsErrors().set(element.name, false);
					} else {
						_this.getElementsErrors().set(element.name, true);
					}
					
				}
				
				if (element.type == 'select-one' || element.type == 'select-multiple') {
					
					result = _this._validateSelected(element);
					if (result) {
						_this.getElementsErrors().set(element.name, false);
					} else {
						_this.getElementsErrors().set(element.name, true);
					}
				}
				
				if (element.type == 'checkbox') {
					
					result = _this._validateChecked(element, count);
					if (result) {
						_this.getElementsErrors().set(element.name, false);
					} else {
						_this.getElementsErrors().set(element.name, true);
					}
					
				}
				
				if (element.type == 'radio') {
					
					result = _this._validateChecked(element, count);
					if (result) {
						_this.getElementsErrors().set(element.name, false);
					} else {
						_this.getElementsErrors().set(element.name, true);
					}
					
				}
				
			}else 
			{
				result = true;
			}
			
			this.toggleErrors();
			
			return result;
			
		},
		
		toggleErrors: function()
		{
			
			var _this = this;
			
			if (this.getHighlightErrors() || this.getShowErrors()) {
				this.getElementsErrors().each(
					function(hash)
					{
						var divId = hash.key.replace('[]', '')+'_error';
						
						if ($(divId) != undefined) {
							if (hash.value) {
								if (_this.getHighlightErrors()) {
									$(divId).addClassName(_this.getHighlightClass());
								}
								if (_this.getShowErrors()) {
									$(divId).show();
								}
							} else {
								if (_this.getHighlightErrors()) {
									$(divId).removeClassName(_this.getHighlightClass());
								}
								if (_this.getShowErrors()) {
									$(divId).hide();
								}
							}
						}
						
					}
						
				);
			}
			
		},
		
		validate: function()
		{
			var errorsCount = 0;
			var _this = this;
			this.getElementsObjects().each(
				function(hash)
				{
					if (!_this.validateElement(hash.key)) {
						errorsCount++;
					}
				}
			);
			
			this.toggleErrors();
			
			if (errorsCount == 0) {
				return true;
			} else {
				return false;
			}
			
		}
	
	}
);
