/*
 * Validation JS
 *
 * - Initializes validation on selector (forms)
 * - Adds/removes rules on elements contained in var wptoolsetValidationData
 * - Checks if elements are hidden by conditionals
 *
 * @see class WPToolset_Validation
 *
 *
 */
var wptValidationForms = [];
var wptValidationDebug = false;
//Contains IDs for CRED form that were already initialised, to prevent multiple initialisation
var initialisedCREDForms = [];

var wptValidation = (function ($) {

	var hasInitBeenPerformed = false;

	function init() {

		if( hasInitBeenPerformed ) {
			return;
		}

		hasInitBeenPerformed = true;

		/**
		 * add extension to validator method
		 */
		$.validator.addMethod("extension", function (value, element, param) {
			param = typeof param === "string" ? param.replace(/,/g, "|") : param;
			if ($(element).attr('res') && $(element).attr('res') != "") {
				return true;
			}
			return ( this.optional(element) || value.match( new RegExp(".(" + param + ")$", "i") ) );
		});

		/**
		 * add hexadecimal to validator method
		 */
		$.validator.addMethod("hexadecimal", function (value, element, param) {
			return ( value == "" || /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value) );
		});

		/**
		 * add method to validate usernames
		 */
		$.validator.addMethod("username", function (value, element, param) {
			return ( value == "" || /^[a-zA-Z0-9\_\-]+$/i.test(value) );
		});

		/**
		 * Added mock "mime_type" validator method because it is presents in wpt-data-validate
		 * on file-related fields. Just in case!
		 */
		$.validator.addMethod("mime_type", function (value, element, param) {
			return true;
		});

		/**
		 * add equalto method
		 */
		$.validator.addMethod("equalto", function (value, element, param) {
			if (param[1]) {
				return ( value == $("input[name='" + param[1] + "']").val() );
			}
			return false;
		});

		/**
		 * add skype to validator method
		 */
		$.validator.addMethod("skype", function (value, element, param) {
			return ( value == "" || /^([a-z0-9\:\.\_\,\-\#]+)$/i.test(value) );
		});

		/**
		 * add extension to validator method require
		 */
		$.validator.addMethod("required", function (value, element, param) {
			var _name = $(element).attr('name');
			var _value = $(element).val();

			// check if dependency is met
			// Last commits includes "required" parameter so this condition is not necessary.
			/*
			if (!this.depend(param, element)) {
				return "dependency-mismatch";
			}
			*/
			switch (element.nodeName.toLowerCase()) {
				case 'select':
					return _value && $.trim(_value).length > 0;
				case 'input':
					if (jQuery(element).hasClass("wpt-form-radio")) {
						var val = jQuery('input[name="' + _name + '"]:checked').val();

						if (wptValidationDebug) {
							console.log("radio " + (typeof val != 'undefined' && val && $.trim(val).length > 0));
						}

						return ( typeof val != 'undefined' && val && $.trim(val).length > 0 );
					}

					var $element = jQuery(element).siblings('input[type="hidden"]').first();
					var elementFieldType = $element.attr('data-wpt-type');
					if ($element
						&& !$element.prop("disabled")
						&& ( elementFieldType == 'file'
							|| elementFieldType == 'video'
							|| elementFieldType == 'image' )
					) {
						var val = $element.val();
						if (wptValidationDebug) {
							console.log("hidden " + (val && $.trim(val).length > 0));
						}

						return ( val && $.trim(val).length > 0 );
					}

					if (jQuery(element).attr('type') == "checkbox") {
						if (wptValidationDebug) {
							console.log("checkbox " + (element.checked));
						}
						return element.checked;
					}

					if (jQuery(element).hasClass("hasDatepicker")) {
						if (wptValidationDebug) {
							console.log("hasDatepicker");
						}
						return false;
					}

					if (this.checkable(element)) {
						if (wptValidationDebug) {
							console.log("checkable " + (this.getLength(value, element) > 0));
						}
						return ( this.getLength(value, element) > 0 );
					}

					if (wptValidationDebug) {
						console.log(_name + " default: " + value + " val: " + _value + " " + ($.trim(_value).length > 0));
					}

					return ( $.trim(_value).length > 0 );
				default:
					return ( $.trim(value).length > 0 );
			}
		});

		/**
		 * Add validation method for datepicker adodb_xxx format for date fields
		 */
		$.validator.addMethod(
			"dateADODB_STAMP",
			function (a, b) {
				return this.optional(b) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(a) && -12219292800 < a && a < 32535215940
			},
			"Please enter a valid date"
		);

		if (wptValidationDebug) {
			console.log("INIT");
			console.log(wptValidationForms);
		}

		_.each(wptValidationForms, function (formID) {
			//Only apply to non CRED elements, CRED ones will be init on cred_form_ready
			if(formID.indexOf('#cred') == -1){
				_initValidation(formID);
				applyRules(formID);
			}
		});
	}

	function _initValidation(formID) {
		if (wptValidationDebug) {
			console.log("_initValidation " + formID);
		}
		var $form = $(formID);
		$form.validate({
			// :hidden is kept because it's default value.
			// All accepted by jQuery.not() can be added.
			ignore: 'input[type="hidden"]:not(.js-wpt-date-auxiliar),:not(.js-wpt-validate)',
			errorPlacement: function (error, element) {
				error.insertBefore(element);
			},
			highlight: function (element, errorClass, validClass) {
				// Expand container
				$(element).parents('.collapsible').slideDown();
				if (formID == '#post') {
					var box = $(element).parents('.postbox');
					if (box.hasClass('closed')) {
						$('.handlediv', box).trigger('click');
					}
				}
				$(element).parent('div').addClass('has-error');
				// $.validator.defaults.highlight(element, errorClass, validClass); // Do not add class to element
			},
			unhighlight: function (element, errorClass, validClass) {
				$("input#publish, input#save-post").removeClass("button-primary-disabled").removeClass("button-disabled");
				$(element).parent('div').removeClass('has-error');
				// $.validator.defaults.unhighlight(element, errorClass, validClass);
			},
			invalidHandler: function (form, validator) {
				if (formID == '#post') {
					$('#publishing-action .spinner').css('visibility', 'hidden');
					$('#publish').bind('click', function () {
						$('#publishing-action .spinner').css('visibility', 'visible');
					});
					$("input#publish").addClass("button-primary-disabled");
					$("input#save-post").addClass("button-disabled");
					$("#save-action .ajax-loading").css("visibility", "hidden");
					$("#publishing-action #ajax-loading").css("visibility", "hidden");
				}
			},
			errorElement: 'small',
			errorClass: 'wpt-form-error'
		});

		// On some pages the form may not be ready yet at this point (e.g. Edit Term page).
		jQuery(document).ready(function () {
			if (wptValidationDebug) {
				console.log($form.selector);
			}

			jQuery(document).off('submit', $form.selector, null);
			jQuery(document).on('submit', $form.selector, function () {
				if (wptValidationDebug) {
					console.log("submit " + $form.selector);
				}

				var currentFormId = formID.replace('#', '');
				currentFormId = currentFormId.replace('-', '_');
				if ( ! _.has( window, 'cred_settings_' + currentFormId ) ) {
					return;
				}
				var cred_settings = window[ 'cred_settings_' + currentFormId ];

				if (wptValidationDebug) {
					console.log("validation...");
				}

				var isAjaxForm = (cred_settings.use_ajax && 1 == cred_settings.use_ajax);
				var isValidForm = $form.valid();

				if (isValidForm) {

					if (wptValidationDebug) {
						console.log("form validated " + $form);
					}

					$('.js-wpt-remove-on-submit', $(this)).remove();

					/**
					 * toolset-form-onsubmit-validate-success
					 *
					 * Event triggered when a cred form on submit is validated
					 *
					 * @since 2.5.1
					 */
					Toolset.hooks.doAction('toolset-form-onsubmit-validation-success', formID, isAjaxForm, cred_settings);

				} else {

					if (wptValidationDebug) {
						console.log("form not valid!");
					}

					/**
					 * toolset-form-onsubmit-validate-error
					 *
					 * Event triggered when a cred form on submit is NOT validated
					 *
					 * @since 2.5.1
					 */
					Toolset.hooks.doAction('toolset-form-onsubmit-validation-error', formID, isAjaxForm, cred_settings);
				}

				//If form is an ajax form return false on submit
				if (isAjaxForm) {

					/**
					 * toolset-ajax-submit
					 *
					 * Event submit of ajax form, it is triggered ONLY when onsubmit belogns to a form that is ajax and it is valid as well
					 *
					 * @since 2.5.1
					 */
					Toolset.hooks.doAction('toolset-ajax-submit', formID, isValidForm, cred_settings);
					return false;
				}
			});
		});
	}

	// @bug This event callback is defined in a limbo never executed, hence the callback will never be fired
	// @bug The event lists used here should be space-separated, otherwise it will get fired at an event with a name
	// "js_event_wpv_pagination_completed," (mind the last comma), which obviously does not exist
	$(document).on('js_event_wpv_pagination_completed, js_event_wpv_parametric_search_results_updated', function (event, data) {
		if (typeof wptValidation !== 'undefined') {
			wptValidation.init();
		}
		if (typeof wptCond !== 'undefined') {
			wptCond.init();
		}
		if (typeof wptRep !== 'undefined') {
			wptRep.init();
		}
		if (typeof wptCredfile !== 'undefined') {
			wptCredfile.init('body');
		}
		if (typeof toolsetForms !== 'undefined') {
			toolsetForms.cred_tax = new toolsetForms.CRED_taxonomy();
			if (typeof initCurrentTaxonomy == 'function') {
				initCurrentTaxonomy();
			}
		}

		if (typeof wptDate !== 'undefined') {
			wptDate.init('body');
		}

		if (typeof jQuery('.wpt-suggest-taxonomy-term') && jQuery('.wpt-suggest-taxonomy-term').length) {
			jQuery('.wpt-suggest-taxonomy-term').hide();
		}
	});

	function isIgnored($el) {
		var ignore = $el.parents('.js-wpt-field').hasClass('js-wpt-validation-ignore') || // Individual fields
			$el.parents('.js-wpt-remove-on-submit').hasClass('js-wpt-validation-ignore'); // Types group of fields
		return ignore;
	}

	function applyRules(container) {
		$('[data-wpt-validate]', $(container)).each(function () {
			_applyRules($(this).data('wpt-validate'), this, container);
		});
	}

	function _applyRules(rules, selector, container) {
		var element = $(selector, $(container));

		if (element.length > 0) {
			if (isIgnored(element)) {
				element.rules('remove');
				element.removeClass('js-wpt-validate');
			} else if (!element.hasClass('js-wpt-validate')) {
				_.each(rules, function (value, rule) {
					var _rule = {messages: {}};
					_rule[rule] = value.args;
					if (value.message !== 'undefined') {
						_rule.messages[rule] = value.message;
					}
					element.rules('add', _rule);
					element.addClass('js-wpt-validate');
				});
			}
		}
	}

	return {
		init: init,
		applyRules: applyRules,
		isIgnored: isIgnored,
		_initValidation: _initValidation
	};

})(jQuery);

jQuery(document).on('toolset_ajax_fields_loaded', function (evt, data) {
	wptValidation._initValidation('#' + data.form_id);
	wptValidation.applyRules('#' + data.form_id);
});

//cred_form_ready will fire when a CRED form is ready, so we init it's validation rules then
jQuery(document).on('cred_form_ready', function (evt, data) {
	if (initialisedCREDForms.indexOf(data.form_id) == -1) {
		wptValidation._initValidation('#' + data.form_id);
		wptValidation.applyRules('#' + data.form_id);
		initialisedCREDForms.push(data.form_id);
	}
});

jQuery(document).ready(function () {

	//init ready CRED forms
	if( typeof( credFrontEndViewModel ) != 'undefined' ) {
		for(var credFormIDIndex in credFrontEndViewModel.readyCREDForms){
			var credFormID = credFrontEndViewModel.readyCREDForms[credFormIDIndex];
			if(initialisedCREDForms.indexOf(credFormID) == -1) {
				wptValidation._initValidation('#' + credFormID);
				wptValidation.applyRules('#' + credFormID);
				initialisedCREDForms.push(credFormID);
			}
		}
	}

	// Note: We call wptValidation.init() to cover all possible edge cases (especially when combined with
	// conditional display of custom fields). Multiple calls do no harm because the init method does nothing
	// if called for the second time and more.

	wptCallbacks.reset.add(function () {
		wptValidation.init();
	});

	wptCallbacks.addRepetitive.add(function (container) {
		wptValidation.init();
		wptValidation.applyRules(container);
	});
	wptCallbacks.removeRepetitive.add(function (container) {
		wptValidation.init();
		wptValidation.applyRules(container);
	});
	wptCallbacks.conditionalCheck.add(function (container) {
		wptValidation.init();
		wptValidation.applyRules(container);
	});
});
