/*
 *
 * Copyright (c) 2009 Doubleclique (dev [at] doubleclique [dot] com)
 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license
 *
 */

/**
 *
 * jquery.dql.forms
 *
 * @name     jquery.dql.forms
 * @version  0.1
 * @author   Kyle Beattie (kyle [at] doubleclique [dot] com)
 * @requires jQuery
 *
 */
/*global jQuery */
"use strict";
(function ($) {
	
	$.fn.forms = function (options) {
		
		var $this = $(this), priv = {}, publ = {};

		options = $.extend(
			{
				errorClass : 'error',
				validClass : 'valid',
				focusClass : 'focus',
				fieldClass : 'element',
				validation : true,
				fieldNoValidationClass : 'novalidation',
				errorMessage : 'Oops, looks like you\'ve missed something. ',
				errorMessageSingle : 'Please enter a value for ',
				errorMessageMultiple : 'Please enter values for ',
				errorMessageClass : 'hint',
				onBlurCallback : ''
			},
			options
		);

		priv.init = function () {

			priv.error = false;

			priv.errorMessage = $('<p></p>').addClass(options.errorMessageClass);

			priv.errorFields = [];

			priv.fieldsArray = [];
			
			priv.$fields = $('input[type="text"], input[type="password"], textarea, select', $this);

			priv.$checkboxes = $('input[type="checkbox"]', $this);

			priv.$hidden = $('input[type="hidden"]', $this);

			priv.$buttons = $('input[type="submit"], input[type="reset"], input[type="image"], input[type="button"], button', $this);

			priv.addEventHandlers();
			
			if (options.validation) {


				priv.doValidation();
				
			}
			
		};

		priv.doValidation = function () {

			var fieldRules = {};
			var fieldMessages = {};
			
			priv.$fields.each(function (index) {

				if (!$(this).hasClass('novalidation')) {

					var rules = {
						required : true
					};
					var classes = $(this).attr('class').split(' ');

					if (classes != '') {

						$(classes).each(function () {

							rules[this] = true;

						});

					}

					fieldRules[$(this).attr('name')] = rules;

					fieldMessages[$(this).attr('name')] = $('label[for="' + $(this).attr('id') + '"]').text() + " is required";

				}				

			});

			priv.$checkboxes.each(function (index) {
				
				if (!$(this).hasClass('novalidation')) {

					var rules = {
						KCW_checkbox : true
					};

					fieldRules[$(this).attr('name')] = rules;

					fieldMessages[$(this).attr('name')] = $('label[for="' + $(this).attr('id') + '"]').text() + " is required";

				}

			});

			$.validator.addMethod("KCW_checkbox", function(value, element) {

				if ($(element).attr('type') == 'hidden') {

					var $checkbox = $('input[type="checkbox"][name="' + $(element).attr('name') + '"]');

				}

				return $checkbox.is(':checked');

			}, "Please check the checkbox.");


			$this.validate({
				ignore : '.novalidation',
				rules: fieldRules,
				messages: fieldMessages,
				focusInvalid : false,
				errorPlacement: function(error, element){
					
					if ($(element).attr('type') == 'hidden') {

						priv.fieldError($('#'+$(element).attr('name')+'_Checkbox', $this));

					} else {

						priv.fieldError($(element));

					}
					
				},
				invalidHandler: function(event, validator) {

					var errors = validator.numberOfInvalids();

					if (errors) {

						$this.prepend(priv.errorMessage.text(options.errorMessage));

						if (typeof options.errorCallback == 'function') {
							
							options.errorCallback();

						}
						
					} else {

						priv.errorMessage.hide();

					}
				},
				showErrors: function(errorMap, errorList) {
					
					this.defaultShowErrors();

				},
				success: function(label) {

					if ($("#"+label.attr('for'), $this).length) {

						priv.fieldValid($("#"+label.attr('for'), $this));

					} else {

						priv.fieldValid($("#"+label.attr('for') + '_Checkbox', $this));

					}
					
				}
			}).hideErrors();
			
		};

		publ.checkFieldValue = function () {

			priv.$fields.each(function (index) {
				
				if ($(this).val() != '') {

					$('label[for="' + $(this).attr('id') + '"]').hide();

				}
				
			});
		};
		
		priv.addEventHandlers = function () {
		
			priv.$fields.each(function (index) {
			
				priv.fieldsArray[index] = $('label[for="' + $(this).attr('id') + '"]').text();

//				if ($(this).val() != '') {
//
//					$('label[for="' + $(this).attr('id') + '"]').hide();
//
//				}

				publ.checkFieldValue();

				var field = $(this);

//				$('label[for="' + $(this).attr('id') + '"]').click(function () {
//					field.focus(); // why @_@
//				});

				$(this).focus(function () {
					priv.fieldFocus($(this));
				});

				$(this).blur(function () {

					priv.fieldBlur($(this));

					if (typeof options.onBlurCallback == 'function') {

						options.onBlurCallback($(this));

					}

				});

			});

			priv.$buttons.each(function (index) {

				$(this).hover(function () {
					
					$(this).parent().addClass('buttonHover');
					
				},function () {

					$(this).parent().removeClass('buttonHover');

				});

				if ($(this).attr('type') == 'reset') {

					$(this).click(function () {
						
						$this.find('.' + options.fieldClass).each( function () {
							
							$(this).removeClass(options.focusClass + ' ' + options.validClass + ' ' + options.errorClass);

						});

						$(this).blur();
						
					});
					
				}

			});

		};

		priv.fieldError = function (field) {
			
			var errorClass = (field.attr('type') == 'hidden' || field.attr('type') == 'checkbox') ? options.errorClass + 'Checkbox' : options.errorClass;

			var validClass = (field.attr('type') == 'hidden' || field.attr('type') == 'checkbox') ? options.validClass + 'Checkbox' : options.validClass;
			
			field.closest('.' + options.fieldClass).removeClass(options.focusClass + ' ' + validClass + ' blurNotEmpty').addClass(errorClass);

		};

		priv.fieldValid = function (field) {
			
			var errorClass = (field.attr('type') == 'hidden' || field.attr('type') == 'checkbox') ? options.errorClass + 'Checkbox' : options.errorClass;

			var validClass = (field.attr('type') == 'hidden' || field.attr('type') == 'checkbox') ? options.validClass + 'Checkbox' : options.validClass;

			field.closest('.' + options.fieldClass).removeClass(options.focusClass + ' ' + errorClass + ' blurNotEmpty').addClass(validClass);

		};

		priv.fieldFocus = function (field) {

			if (field.val() == '') {

				$('label[for="' + field.attr('id') + '"]').hide();

			}

			field.closest('.' + options.fieldClass).removeClass(options.errorClass + ' ' + options.validClass + ' blurNotEmpty').addClass(options.focusClass);

		};

		priv.fieldBlur = function (field) {

			if (field.val() != '') {

				$('label[for="' + field.attr('id') + '"]').hide();
				
			} else {

				$('label[for="' + field.attr('id') + '"]').show();

			}
			
			field.closest('.' + options.fieldClass).removeClass(options.focusClass);
						
		};

		priv.updateErrorMessage = function ($field, index) {
			
			var label = $('label[for="' + $field.attr('id') + '"]').text();

			priv.errorFields[index] = label;

			if (!priv.error) {

				priv.errorMessage.text(options.errorMessage + options.errorMessageSingle + label);
				
				$this.prepend(priv.errorMessage);

				priv.error = true;

			} else {

				priv.errorFields[index] = label;

				var fields = '';

				$(priv.errorFields).each(function (errorIndex) {

					if (priv.errorFields[errorIndex] !== undefined) {
						fields += priv.errorFields[errorIndex];

						if (errorIndex !== (priv.errorFields.length - 1)) {
							fields += ', ';
						}
					}

				});

				priv.errorMessage.text(options.errorMessage + options.errorMessageMultiple + fields);

			}

		};

		priv.init();

		//publ.checkFieldValue();

		return publ;

	}
	
}(jQuery));

