/**
 * @copyright: Edd Couchman for Vuture (vuture.co.uk)
 *             
 * @version:   0.8.5
 *             
 * @requires:  prototype.js version 1.6 or above. Works in Safari 1.2+, Firefox 1.0+, IE6+
 *             
 * @usage:     After the relevant <script> tag, add the following code:
 *             <script type="text/javascript">
 *             //<![CDATA[
 *             new Validation(reference_to_form);
 *             //]]>
 *             </script>
 * 	           
 * @note:      reference_to_form can either be a string containing the form's ID: i.e., 'login_form'
 *             or a reference to an element: i.e., document.getElementsByTagName('form')[0]
 *             
 * @note:      Each input element must be within a <p> for accessibility (and this class to work!)
 *             
 * @note:      At the moment, only the validation_rules.email has been tested thoroughly
 *             
 */

var Validation = Class.create({
	initialize: function(element) {
		this.element = $(element);
		this.invalid_elements = 0;
		this.form_elements = this.element.getElements();
		
		// regex rules for validating email addresses and dates
		this.validation_rules = {
			email: {
				message: 'Please enter a valid email address',
				regex: /^[A-Za-z\/-9!#-'*+\-\/=?_`{-~^]([A-Za-z.-9!#-'*+\-\/=?_`{-~^]*[A-Za-z\/-9!#-'*+\-\/=?_`{-~^])?@([A-Za-z0-9]+\.)+[A-Za-z0-9]+\.?$/i
			},
			
			phone: {
				message: 'Sorry, but your phone number doesn\'t look valid',
				regex: /^[0-9\s\(\)\+#\-\*]{6,21}$/i
			},
			
			date: {
				message: 'The date should be in the format dd/mm/yyyy',
				regex: /^[0-3][0-9]\/[0-1][0-9]\/[12][0-9]{3}\/$/
			}
		};
		
		// validate on submit
		this.element.observe('submit', function(event) {
			this.invalid_elements = 0;
			
			this.form_elements.each(function(input) {
				input = $(input);
				
				var is_valid_element = true;
				var tag_name = input.tagName.toLowerCase();
				
				// run the relevant checks depending on input type
				switch ( tag_name ) {
					case 'input':    is_valid_element = ( this.checkBlank(input) && this.checkEmail(input) ) ? true : false; break;
					case 'textarea': is_valid_element = ( this.checkBlank(input) ) ? true : false; break;
					case 'select':   is_valid_element = ( this.checkFirst(input) ) ? true : false; break;
					default:         is_valid_element = ( this.checkBlank(input) ) ? true : false; break;
				}
				
				// either mark the input as bad, or clear it's status
				( is_valid_element ) ? input.clearError() : ++this.invalid_elements;
				
				return input;
			}.bind(this));
			
			// stop the form submission if there are bad elements
			if ( this.invalid_elements > 0 ) { event.stop(); }
		}.bindAsEventListener(this));
		
		// reset the validator when the form is reset
		this.element.observe('reset', this.reset.bindAsEventListener(this));
		
		return this;
	},
	
	checkBlank: function(input) {
		input = $(input);
		
		// if the input has a 'required' classname, check it
		if ( input.hasClassName('required') ) {
			if ( $F(input).blank() ) {
				input.errorMessage();
				return false;
			}
		}
		
		return true;
	},
	
	checkFirst: function(input) {
		input = $(input);
		
		// if the input has a 'validate-selection' classname, check it
		if ( input.hasClassName('validate-selection') ) {
		
			if ( $F(input) == input.down('option').readAttribute('value') ) {
				input.errorMessage();
				return false;
			}
		
		}
		return true;
	},
	
	checkEmail: function(input) {
		input = $(input);
		
		// if the input has a 'validate-email' classname, check it
		if ( input.readAttribute('type') == 'text' && input.hasClassName('validate-email') ) {
			if ( !(this.validation_rules.email.regex).test($F(input)) ) {
				input.errorMessage();
				return false;
			}
		}
		
		return true;
	},
	
	reset: function() {
		// this function resets this Validation class
		this.invalid_elements = 0;
		
		this.form_elements.each(function(input) {
			return $(input).clearError();
		}.bind(this));
	}
});

Object.extend(
	Form.Element.Methods, {
		// method to add an error message
		errorMessage: function(element) {
			element = $(element);
			if ( element.up('p') ) {
				$(element).up('p').addClassName('error_message');
			}
		
			return element;
		},
	
		clearError: function(element) {
			// method to clear an error message
			element = $(element);
			if ( element.up('p') ) {
				$(element).up('p').removeClassName('error_message');
			}
		
			return element;
		}
	}
);

Element.addMethods(); // add the Form.Element.Methods from above