/**
 * @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();
		this.messages = $A();
		
		// regex rules for validating email addresses and dates
		this.validation_rules = {
			email: {
				message: 'Please enter a valid email address',
				regex: /^[\w\.=-]+@[\w\.-]+\.[a-zA-Z]{2,21}$/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.messages = $A();
			
			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) && this.checkOne(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 ) ? this.clearError(input) : ++this.invalid_elements;
				
				return input;
			}, this);
			
			// stop the form submission if there are bad elements
			if ( this.invalid_elements > 0 ) {
				event.stop();
				if (this.messages.size === 0) {
					alert('Merci de rentrer votre information.');
				} else {
					alert('• ' + this.messages.join('\n• '));
				}
			}
		}.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() ) {
				this.errorMessage(input);
				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') ) {
				this.errorMessage(input);
				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)) ) {
				this.errorMessage(input);
				return false;
			}
		}
		
		return true;
	},
	
	checkOne: function(input) {
		input = $(input);
		
		if (input.hasClassName('validate-one')) {
			var checked = $w(input.className).without('validate-one').inject(false, function (accumulator, class_name) {
				if (this.element.select('.' + class_name).pluck('checked').include(true)) {
					return true;
				} else {
					this.errorMessage(input);
				}
				
				return accumulator;
			}, this);
			
			return checked;
		}
		
		return true;
	},
	
	reset: function() {
		// this function resets this Validation class
		this.invalid_elements = 0;
		this.messages = $A();
		
		this.form_elements.each(function(input) {
			return this.clearError(input);
		}, this);
	},
	
	errorMessage: function(element) {
		element = $(element);
		if (element.up('p')) {
			$(element).up('p').addClassName('error_message');
		}
		
		if (element.title) {
			this.messages.push(element.readAttribute('title'));
		}
		
		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;
	}
});
