/**
 * Validation Class
 * Dependencies: Mootools v1.2+ 
 * @author Kevin Dew <kev@dewsolutions.co.uk>
 * @copyright Copyright Kevin Dew, 2008
 */

var Validation = new Class(
{
	/**
	 * Set validation object to initial state
	 * 
	 * @param	array	Validation rules array
	 * @param	string	Top error i.e "This form cannot be submit because"
	 * @param	string	Class to change erroneous formfields too
	 * @param	string	The id of the form element to perform this validation on
	 */
	initialize: function(valArr, topErrStr, errorClassStr, formElId)
	{
		this.rules = valArr;
		this.topError = topErrStr;
		this.errorClass = errorClassStr;
		this.formEl = $(formElId);
		this.errors = [];
		// -1 = not tested, 0 = errors, 1 = no errors
		this.result = -1;
	},
	/**
	 * Function to test the form fields for errors
	 */
	test: function()
	{
		this.result = 1;
		for(var i = 0; i < this.rules.length; i++)
		{
			var rule = this.rules[i];
			//only test fields that exist
			if($(rule.field))
			{
				//first see if the field is blank
				if(!this.testBlank($(rule.field).get('value')))
				{
					if(rule.blank)
					{
						$(rule.field).addClass(this.errorClass);
						this.errors.push(rule.blankErr);
						this.result = 0;
					}
				}
				else
				//then regexp / custom functions
				{
					if($type(rule.regExp))
					{
						if(!this.testRegExp(rule.regExp, $(rule.field).get('value')))
						{
							$(rule.field).addClass(this.errorClass);
							this.errors.push(rule.regExpErr);
							this.result = 0;
						}
					}
					if($type(rule.callBack) == 'function')
					{
						if(rule.callBack($(rule.field).get('value')) != '')
						{
							$(rule.field).addClass(this.errorClass);
							this.errors.push(rule.callBack($(rule.field).get('value')));
							this.result = 0;
						}
					}
				}
				//always run call back
				if($type(rule.arCallBack) == 'function')
				{
					if(rule.arCallBack($(rule.field).get('value')) != '')
					{
						$(rule.field).addClass(this.errorClass);
						this.errors.push(rule.arCallBack($(rule.field).get('value')));
						this.result = 0;
					}
				}
			}
		}
		return this.result;
	},
	/**
	 * test if a field is blank
	 */
	testBlank: function(valueMix)
	{
		return !(valueMix == '');
	},
	/**
	 * test a regular expression on a field
	 */
	testRegExp: function(regExp, valueMix)
	{
		return regExp.test(valueMix);
	},
	/** 
	 * Take errors and make a html list and add that to the form
	 */
	makeErrorList: function()
	{
		if(this.formEl)
		{
			//create errors
			if($(this.formEl.getProperty('id') + '_errors'))
				var div = $(this.formEl.getProperty('id') + '_errors').addClass('val_errors');
			else
				var div = new Element('div', {'id': this.formEl.getProperty('id') + '_errors', 'class': 'val_errors'});
			
			div.appendChild(new Element('p', {}).appendText(this.topError));
			var ul = new Element('ul', {});
			div.appendChild(ul);
			for(var i = 0; i < this.errors.length; i++)
				ul.appendChild(new Element('li', {}).appendText(this.errors[i]));
			
			if(!$(this.formEl.getProperty('id') + '_errors'))
				div.injectBefore(this.formEl.getFirst());
			else if(div.hasClass('hide'))
				div.removeClass('hide');
		}	
	},
	/**
	 * reset state for a retry of a validation
	 */
	clearErrors: function()
	{
		this.result = -1;
		this.errors = [];
		if($(this.formEl.getProperty('id') + '_errors'))
		{
			$each($(this.formEl.getProperty('id') + '_errors').getChildren(), function(e)
			{
				e.destroy();
			});
			$(this.formEl.getProperty('id') + '_errors').addClass('hide');
		}
		this.formEl.getChildren().removeClass(this.errorClass);
	},
	/** 
	 * Method to run the validation procedure
	 */
	run: function()
	{
		this.clearErrors();
		if(!this.test())
		{
			this.makeErrorList();
			return false;
		}
		return true;
	},
	addError: function(fieldStr, errorStr)
	{
		if((fieldStr != '') && $(fieldStr))
			$(fieldStr).addClass(this.errorClass);
		this.result = 0;
		this.errors.push(errorStr);
	},
	hasErrors: function()
	{
		return (this.result == 0);
	}
	
	
});

