/*
 Adapted by Doli Stepniewski <doli@justapinch.com>
 From zendcast.com

 Assumes Default Zend Form Decorators are used:
 form
	dl
		dd id="<element_id>-label"
			label for = "<element_id>"
		/dd
		dt id="<element_id>-element"
			element id="<element_id>"
		/dt
	/dl
 /form

 and for checkboxes
 form
	dl
		dd id="<element_id>-element"
			label for = "<element_id>"
		/dd
		dt id="<element_id>-label"
			element id="<element_id>"
		/dt
	/dl
 /form

*/
$.fn.zendValidate = function(opt){
	return this.each(function(){
		var ZV = this;
		var form = $(this);
		var data = {};
		var queue = [];

		ZV.option = {
			url: false,
			validateOnLoad: false,
			emailAction: false,
			onSubmit: true
		};

		ZV.option = $.extend(ZV.option,opt);

		ZV.abort = function() {
			var requests = queue.length;
			for (var i = 0; i< requests; i++) {
				queue[i].abort();
			}
			queue = [];
		}

		ZV.doValidation = function(id, func){
			var dd;
			if ($('#'+id).attr('type') == 'checkbox') {
				dd = form.find('#'+id+'-label');
			} else {
				dd = form.find('#'+id+'-element');
			}
			var data = {};

			dd.removeClass('error').find('.errors').remove();
			dd.find('.status').remove();
			dd.append('<span class="status"><span class="loading-16" title="Validating"></span></span>');

			// clear previous requests, so we only have one expecting a result. last in wins
			ZV.abort();
			var $x = $.post(ZV.option.url, form.serialize(), function(resp) {
				ZV.data = resp;
				if (ZV.data) {
					ZV.setError(id);
				} else {
					flash_alert_hide();
				}
				if(typeof func == 'function') {
					func();
				}
			},'json');
			queue.push($x);
		}

		ZV.setError = function(id){
			var dd;
			if ($('#'+id).attr('type') == 'checkbox') {
				dd = form.find('#'+id+'-label');
			} else {
				dd = form.find('#'+id+'-element');
			}
			dd.find('.status').remove();
			dd.removeClass('error').find('.errors').remove();

			if(id=='email' && typeof ZV.option.emailAction == 'function' &&  ZV.data[id] != undefined && ZV.data[id].alreadyUsed != undefined ){
				ZV.option.emailAction();
				return;
			}
			dd.append(ZV.getStatus(ZV.data[id],id));
			dd.append(ZV.getHtmlError(ZV.data[id],id));
		}

		ZV.getHtmlError = function(formErrors,id){
			var o = '';
			for (errorKey in formErrors){
				o += '<li>'+formErrors[errorKey]+'</li>';
			}
			if(o.length){
				return '<ul id="errors-'+id+'" class="errors zend-validate-errors">' + o + '</ul>';
			}
			return '';
		}

		ZV.getStatus = function(formErrors,id){
			var s = '<img src="/images/icons/accept.png" alt="Valid" />';
			for (errorKey in formErrors){
				s = '<img src="/images/icons/exclamation.png" alt="Invalid" />';
			}
			return '<span id="status-'+id+'" class="status">' + s + '</span>';
		}

		ZV.validateForm = function(focusFirst) {
			var e = '';
			var valid = true;
			var firstelementid = false;
			// abort any other validation
			ZV.abort();

			$.ajax({
				async: false,
				type: 'POST',
				url: ZV.option.url,
				data: form.serialize(),
				success: function(resp) { ZV.data = resp; },
				dataType: 'json'
			});

			for(obj in ZV.data){
				if(!firstelementid){
					firstelementid = obj;
				}
				ZV.setError(obj);
				valid = false;
			}
			if(valid){
				flash_alert_hide();
				return true;
			} else {
				flash_alert('There are some items on the form that need your attention.');
				if(focusFirst){
					scrollToTag('#'+firstelementid+'-label');
					$('#'+firstelementid).focus();
				}
				return false;
			}
		}

		ZV.setup = function(){
			if(ZV.option.url){
				$('.validate').not(':submit').not('select').blur(function() {
					var formElementId = $(this).parent().prev().find('label').attr('for');
					if (this.type == 'checkbox' && !formElementId) {
						formElementId = $(this).parent().next().find('label').attr('for');
					}
					ZV.doValidation(formElementId);
				});
				$('select .validate').change(function(){
					var formElementId = $(this).parent().prev().find('label').attr('for');
					ZV.doValidation(formElementId);
				});

				if(ZV.option.validateOnLoad){
					ZV.doValidation(null, function(){ZV.validateForm(false)});
				} else {
					ZV.doValidation();
				}

				if (ZV.option.onSubmit) {
					form.submit( function( event ) {
						var valid = ZV.validateForm(true);
						if (valid) {
							//disable the submit button, so people don't double charge
							$submit = $(':submit', this);
							$submit.after('<span class="loading-32" style="margin:10px;"></span>');
							$submit.hide();
						}
						return valid;
					});
				}
			}
		}

		ZV.init = function() {
			ZV.setup();
		}

		ZV.init();
	});
}
