var formElements = new Array('input', 'textarea', 'select', 'button');

var ValidateFrom = Element.implement({

	/**
	 * Attach event for each element of the form to validate
	 * Will loop on each form fields and attach an event handler which
	 * trigger a unit field validation each time the event is fired
	 *
	 * @return element
	 * @author Laurent Goussard
	 **/
	autoValidate: function()
	{
		var form = this;

		this.getElements( formElements.join(',') ).forEach(function(item, index){
			if( formElements.indexOf( item.get('tag') ) >= 0 )
			{
				item.addEvents({
					'change': form.validateForm.bind(form),
					'select': form.validateForm.bind(form),
					'focus': form.validateForm.bind(form),
					'keyup': function() {
						$clear(item.keyUpTimer);
						item.keyUpTimer = form.validateForm.delay(500, form);
					}
				});
			}
		});
		return this;
	},

	/**
	 * Auto check form content
	 * Will loop on each form field and try to find an "accept" attribute
	 * If this attribute exists, it will verify if the field value or amount match the expression contained in the accepted attribute.
	 * A valid match will add a "valid" class name to the current field. Otherwise an "invalid" class name will be added.
	 * Once all the form has been check, if no error were found, the form will trigger a "valid" event.
	 *
	 * @return boolean
	 * @author Laurent Goussard
	 **/
	validateForm: function ()
	{
		var invalid_items = Array();

		this.getElements( formElements.join(',') ).forEach(function(element, i){
			if( formElements.indexOf( element.get('tag') ) >= 0 && $chk(element.getProperty('accept')))
			{
				var validation = element.validateField();
				if(!validation)
				{
					invalid_items.push(element);
				}
			}
		});
		if(invalid_items.length > 0)
		{
			return;
		}
		this.fireEvent('valid');
		return;
	},

	/**
	 * Unit field validation test
	 * Try to find an "accept" attribute and verify if the field value or amount match the expression contained in it.
	 * A valid match will add a "valid" class name to the current field. Otherwise an "invalid" class name will be added.
	 *
	 * @return boolean
	 * @author Laurent Goussard
	 **/
	validateField: function(forceFormValidation)
	{
		if( formElements.indexOf( this.get('tag') ) >= 0 && $chk(this.getProperty('accept')))
		{
			var form = this.getParent();
			while(form.get('tag') != 'form')
			{
				form = form.getParent();
			}

			var check = this.getProperty('accept').replace(/parent/gi, 'form');
			var result = eval(check);
			var switch_class;
			if( result )
			{
				switch_class = {add:'valid', remove:'invalid'};
				if(forceFormValidation)
				{
					form.validateForm(); // Force form validation
				}
			}
			else
			{
				switch_class = {add:'invalid', remove:'valid'};
				form.fireEvent('invalid'); // Force form invalidation
			}

			this.removeClass( switch_class.remove );
			this.addClass( switch_class.add );
			this.fireEvent( switch_class.add ); // Fire element state

			return result;
		}
	},

	/**
	 * Add a validation condition
	 * Add a validation condition on the fly to the current field
	 *
	 * @param string validation is supposed to match
	 * @param string operator. Default is &&
	 * @author Laurent Goussard
	 **/
	addCondition: function(string, operator)
	{
		operator = (operator) ? operator : '&&';
		if( formElements.indexOf( this.get('tag') ) >= 0 && $chk(this.getProperty('accept')))
		{
			var check = this.getProperty('accept');
			check = check.split(';');
			check.push(string);

			for( var i = 0 ; i <check.length; i++ )
			{
				if( !check[i])
				{
					check.splice(i,1);
				}
			}

			this.setProperty('accept', check.join(' '+operator+' '));
		}
	}

});