/* 	
  Author: Allen Leis (Govtrends)
  Date: September 30, 2009
  
  Custom Validators:
  		custom validators must return an array of objects that failed validation.  Each object
  		should be of the form {el : elementThatFailed, msg : 'Error message to display'}
 
  TODO: 1) Rewrite using decorators
  		2) Rewrite max length feature to compute intended max length
 */
YAHOO.util.Event.onDOMReady(function(){
	
	YAHOO.burris.validator = function(){
		var forms,errorsFound,firstEl = false;
		var customValidators = [];
		var failedValidation = [];
		
		var addCustomValidator = function(form,fnc) {
			var form = (typeof(form) == 'string') ? document.getElementById(form) : form;
			var obj = { form : form, fnc : fnc };
			forms.push(obj);
			return obj;
		};
		
		var removeCustomValidator = function(obj) {
			if (customValidators.indexOf(obj) != -1) {
				customValidators.remove(customValidators.indexOf(obj))
				return true;
			} 
			return false;
		};
		
		var showErrorMessage = function(el,msg){
			var el = (typeof(el) == "string") ? document.getElementById(el): el;
			if (failedValidation.indexOf(el) == -1) {
				failedValidation.push(el);
				if (!errorsFound) {firstEl = el; errorsFound = true;}
				var div = document.createElement("div");
				div.innerHTML = msg;
				YAHOO.util.Dom.addClass(div,"red validation-msg");
				YAHOO.util.Dom.insertAfter(div,el);
			}
			errorsFound = true;
		};
		
		var clearErrorMessages = function(form) {
			var nodes = YAHOO.util.Selector.query('.validation-msg',form);
			for (n=0;n < nodes.length;n++) {
				nodes[n].parentNode.removeChild(nodes[n]);
			} 
			failedValidation = [];
			errorsFound = false;
		};
		
		// handle required fields
		function processRequiredFields(form){
			var required = YAHOO.util.Selector.query('.required',form);
			required.forEach(function(el){
				if ((el.tagName == 'INPUT') || (el.tagName == 'TEXTAREA')) {
					if (el.value.replace(/ /g,"") == "") {
						showErrorMessage(el,'The ' + YAHOO.util.Dom.getAttribute(el,'title') + ' field is required');
					};
				}
			});
		};

		// handle max length fields
		function processMaxLengthFields(form){
			var lengths = [{className:'maxlength100',length:100},{className:'maxlength40',length:40},{className:'maxlength25',length:25}];
			
			lengths.forEach(function(obj){
				var elements = YAHOO.util.Selector.query('.' + obj.className,form);
				elements.forEach(function(el){
					if (el.value.length > obj.length) showErrorMessage(el,'The ' + el.getAttribute('title')+ ' field is ' + (el.value.length - obj.length) + ' characters too long -  please reduce to ' + obj.length + ' characters');
				});
			});
		};

		function processCustomValidators(form){
			forms.forEach(function(v){
				if (v.form == form) {
					var errors = v.fnc.call(form);
					errors.forEach(function(error){
						showErrorMessage(error.el,error.msg);
					});
				}
			});
		};

		function processFormatSpecificFields(form){
			var formats = [{classname : 'email', re : /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i }];
			formats.forEach(function(format){
				var elements = YAHOO.util.Selector.query('.' + format.classname,form);
				elements.forEach(function(el){
					if (el.tagName == 'INPUT') {
						if (el.value.search(format.re) == -1) {
							showErrorMessage(el,'The ' + YAHOO.util.Dom.getAttribute(el,'title') + ' field is the wrong format');
						};
					}
				});
			});
		};
		
		
		function validate(e){
			clearErrorMessages(this);
			processRequiredFields(this);
			processFormatSpecificFields(this);
			processMaxLengthFields(this);
			processCustomValidators(this);
			if (errorsFound) {
				YAHOO.util.Event.preventDefault(e);
				firstEl.focus();
			}
		};
		
		function init(){
			forms = YAHOO.util.Selector.query('form');
			forms.forEach(function(f){
				YAHOO.util.Event.on(f,'submit', validate);
			});
		};
		init();
		
		return {
			addCustomValidator : addCustomValidator,
			removeCustomValidator : removeCustomValidator
		};
		
	}();	
});