var AsyncForms = DUI.Class.create({
	forms: new Array(),
	registerForm: function(form) {
		this.forms[form.formID] = form;
		form.install();
	}
}, true);

var AsyncForm = DUI.Class.create({
	fields : new Array(),	
	formID : '',	
	formURL : '',	
	singleValidation : false,	
	validating : false,	
	currentField : "",			
	applyValidationResults : function(results) {
		var count = 0;		
		var first = null
		for(var result in results.errors) {
			$("#" + result + "Error").html(results.errors[result]);
			$("#" + result + "Error").fadeIn("slow");
			if (count == 0) {
				first = $("#" + result);
			}		
			count++;
		}	
	
		if (!this.singleValidation) {
			for(var field in this.fields) {
				if (field.form != results.form) {
					continue;
				}
				if (results.errors[field] == undefined) {
					$("#" + field + "Error").html("");
					$("#" + field + "Error").fadeOut("slow");		
				}
			}
		} else {
			if (results.errors[this.currentField] == undefined) {
					$("#" + this.currentField + "Error").html("");
					$("#" + this.currentField + "Error").fadeOut("slow");		
			}			
		}		
		
		if (!this.singleValidation && (count == 0)) {		
			$("#" + results.form)[0].submit();			
		} else  if (!this.singleValidation) {
			first.focus();
		}
		
		
	},		

	performFormValidation: function (fields) 
	{
		if (this.validating)
			return;
			
		this.validating = true;	
		
		fields[fields.length] = {name: "form", value: this.formID};
				
		$.post(this.formURL, fields, function(data) {			
			var asyncForm = AsyncForms.forms[data.form];
			asyncForm.applyValidationResults(data);
			asyncForm.singleValidation = false;	
			asyncForm.currentField = "";
			asyncForm.validating = false;		
		}, "json");
	},
	
	registerForm: function (index, form) {
				
		$(form).submit( function () {			
			var asyncForm = AsyncForms.forms[this.id];			
			asyncForm.validateForm();
			return false;
		})
		
		return false;
	},
	
	registerField : function (index, field) {		
		var asyncForm = AsyncForms.forms[field.form.id];
		var fieldName = field.id;		
		$("#" + fieldName+ "Error").each( function() {
			if ($(this).text() == "") {
				$(this).hide();
			}
		})
		
		asyncForm.fields[fieldName] = {name : fieldName, value:  $("#" + fieldName).val(), form: asyncForm.formID};
		
		$("#" + fieldName).blur( function() {
			
			if (!asyncForm.validating) {
				asyncForm.singleValidation = true;									  	
				asyncForm.currentField = fieldName;
				asyncForm.validateField(fieldName);
			}
		});	
		
	},
	
	validateField: function (fieldName) {
		this.fields[fieldName].value = $("#" + fieldName).val();
		var fields = [this.fields[fieldName]];
		this.performFormValidation(fields);	
	},
	

	validateForm : function () {	
		var index = 0;
		fields = new Array();
		for (var name in this.fields) {
			if (this.fields[name].form != this.formID) {
				continue;
			}
			if ($("#" + name).length >0)
			{
				if ($("#" + name)[0].type == "radio") {
					this.fields[name].value = $("#" + name)[0].checked? $("#" + name).val() : "";
				} else {
					this.fields[name].value = $("#" + name).val();
				}
			}		
			fields[index++] = this.fields[name];
		}
		this.singleValidation = false;
		this.currentField = "";
		this.performFormValidation(fields);			
		return false;
	},
	
	
	init: function(formID, formURL) {
		this.formID = formID;
		this.formURL = formURL;			
		var form = this;				
	},
	
	install: function() {
		$("#" + this.formID).each(this.registerForm);			
		$("#" + this.formID + " .asyncValidation").each(this.registerField);		
	}
});

(function($) {
	$.fn.asyncSubmit = function() {
	  return this.each(function(){
	    if (this.nodeName == "FORM") {
			AsyncForms.registerForm(new AsyncForm(this.id, this.action)); 
		}
	  });
	};
})(jQuery);