(function($){
	$.ssFormValidate = function(el, options){
		var base = this;

		// Access to jQuery and DOM versions of element
		base.$el = $(el);
		base.el = el;

		// Add a reverse reference to the DOM object
		base.$el.data("ssFormValidate", base);

		base.init = function(){
			base.options = $.extend({},$.ssFormValidate.defaultOptions, options);
			
			base.display	= base.options.display;
			
			base.valid	= true;
			
			base.method	= base.$el.attr('method') || 'ajax';
			
			$(base.options.selectors, base.$el).each(
				function() {
					$(this).bind(base.options.binding, function() {
						base.validate($(this));
					});
				}
			);
			
			base.$el.submit(
				function(e) {
					if (base.validateAll()) {
						base.options.beforeSubmit();
						if (base.method == 'ajax') {
							e.preventDefault();
							
							$.ajax({
								type: 'POST',
								url: base.$el.attr('action'),
								data: base.$el.serialize(),
								dataType: base.options.response_type,
								success: function (data, textStatus, jqXHR) {
									base.options.success(data, textStatus, jqXHR, base.$el);
								}
							});
						}
					} else {
						e.preventDefault();
						base.options.notValid()
					}
				}
			)
		};
		
		base.showLoading = function() {
			$(document.body)
				.append(
					$('<div/>')
						.attr('id', 'loading_div')
						.css({'top': '0px', 'width':$(window).width(),'height':$(document).height()})
						.css({'position': 'absolute', 'cursor': 'wait'})
						.css({'z-index': '9999'})
						.append('&nbsp;')
				)
		}
				
		base.hideLoading = function() {
			$('#loading_div').remove();
		}
		
		base.resetForm = function() {
			$(':input', base.$el).each(function() {
				var type = this.type;
				var tag = this.tagName.toLowerCase(); // normalize case
				if (type == 'text' || type == 'password' || tag == 'textarea')
					this.value = "";
				else if (type == 'checkbox' || type == 'radio')
					this.checked = false;
				else if (tag == 'select')
					this.selectedIndex = -1;
			});
		};
		
		base.validateEmailAddress = function(str) {
			var atPos = str.indexOf('@',0);
			var suffix = str.substring(str.lastIndexOf('.')+1);
			
			switch (true) {
				case (str == ''):
				case (atPos == 0):
				case (atPos == -1):
				case (str.indexOf('@', atPos + 1) > - 1):
				case (str.indexOf('.', atPos) == -1):
				case (str.indexOf('@.',0) != -1):
				case (str.indexOf('.@',0) != -1):
				case (str.indexOf('..',0) != -1):
				case (suffix.length != 2 && suffix != 'com' && suffix != 'net' && suffix != 'org' && suffix != 'edu' && suffix != 'int' && suffix != 'mil' && suffix != 'gov' & suffix != 'arpa' && suffix != 'biz' && suffix != 'aero' && suffix != 'name' && suffix != 'coop' && suffix != 'info' && suffix != 'pro' && suffix != 'museum'):
					return false;
					break;
			}
			
			return true;
		};
		
		base.validateAll = function() {
			var valid = true;
			
			$(base.options.selectors, base.$el).each(
				function() {
					if (!base.validate($(this)))
						valid = false;
				}
			);
			
			return valid;
		}
		
		base.valueChanged = function(context) {
			var defaultVal	= context[0].defaultValue;
			var currentVal	= context.val();
			
			return ((currentVal != defaultVal) && (currentVal != ''))
		}
		
		base.validate = function(context) {
			var valid	= true;
			var type	= context.attr('rel') || null;
			
			//console.debug(context.attr('rel'))
			
			if (type) {
				switch(type) {
					case "email":
						valid	= base.showValidation(context, base.validateEmailAddress(context.val()));
						break;
					
					default:
						valid	= base.showValidation(context, base.valueChanged(context));
						break;
				}
			}
			
			return valid;
		};
		
		base.showValidation = function(context, valid) {
			if (valid) {
				if (base.options.label_class)
					$('label[for=' + context.attr('id') + ']').removeClass(base.options.label_class)
				
				if (base.options.field_class)
					context.removeClass(base.options.field_class)
			} else {
				if (base.options.label_class)
					$('label[for=' + context.attr('id') + ']').addClass(base.options.label_class)
				
				if (base.options.field_class)
					context.addClass(base.options.field_class)
			}
			return valid;
		}

		// Run initializer
		base.init();
	};
	
	$.ssFormValidate.defaultOptions = {
		selectors:		'input,textarea,select',
		binding:		'change blur',
		label_class:	'not_valid',
		field_class:	'not_valid',
		beforeSubmit:	function () {},
		notValid:		function () {},
		success:		function (data, textStatus, jqXHR) {}
	};
	
	$.fn.ssFormValidate = function(options){
		return this.each(function(){
			(new $.ssFormValidate(this, options));
		});
	};
	
})(jQuery);
	
