!function($){
	$.fn.extend({
		form: function(url, inputs, options, context) {
			return this.each(function() {
				var $form = $(this);
				function getUrl() {
					return _.isFunction(url) ? url() : url;
				}
				function submit() {
					if(validate()) {
						$.ajax({
							url: getUrl(),
							contentType: options.json ? 'application/json' : 'application/x-www-form-urlencoded',
							data: data(options),
							type: 'POST',
							success: function(response) {
								clear();
								options.success && options.success.call(context, response);
							}
						});
					}
					return false;
				}
				function data(options) {
					var data = {};
					$.each(inputs, function(key) {
						data[key] = val(key);
					});
					return options.json ? JSON.stringify(data) : data;
				}
				function field(key) {
					return $form.find(getSelector(key));
				}
				function getSelector(key) {
					return inputs[key] ? inputs[key] : '[name="' + key + '"]';
				}
				function val(key) {
					return field(key).val();
				}
				function addError($element, message) {
					$element.parents('.js-validate').addClass('error');
					if(message) {
						$element.parent().append('<span class="help-block js-error-msg">'+message+'</span>');
					}
				}
				function removeErrors() {
					$('.js-error-msg').remove();
					$('.error').removeClass('error');
				}
				function clear() {
					$.each(inputs, function(key) {
						field(key).val('');
					});
				}
				function validate() {
					var status = true;
					removeErrors();
					$.each(inputs, function(key) {
						var keyStatus = true;
						$form.find(getSelector(key) + '.required').each(function() {
							if($(this).val().trim().length <= 0) {
								addError($(this), "Please enter " + $form.find('[for='+key+']').html().replace('*','') + ".");
								status = false;
								keyStatus = false;
							}
						});
						if(keyStatus) {
							$form.find(getSelector(key) + '.email').each(function() {
								if($(this).val().indexOf('@') < 0 || $(this).val().indexOf('.') < 0) {
									addError($(this), $form.find('[for='+key+']').html().replace('*','') + " must be a proper email address.");
									status = false;
									keyStatus = false;
								}
							});
						}
						/*	TODO: Get match working
						 * if(keyStatus) {
							$form.find(getSelector(key) + '[match]').each(function() {
								if($(this).val() != $form.find($(this).attr('match')).val()) {
									addError($(this), $form.find('[for='+key+']').html() + " and " + $form.find('[for=' + $form.find($(this).attr('match')) + ']').html() + " do not match.");
									status = false;
								}
							});
						}*/
					});
					return status;
				}
				$(this).delegate('.js-form-submit', 'click', submit);
			});
		}
	});
}(jQuery);
