﻿var objJSON;

jQuery(function () {
	objJSON = loadErrorMessages();
	//if (jQuery("#posted") == null || jQuery("#posted").val() == "0") {
		bindValidationRules(document);
	//}
});

function loadErrorMessages() {
	var returnValue;
	var theURL;

	if (window.location.href.indexOf("https://") > -1) {
		theURL = 'https://' + document.location.hostname  + '/messages.ashx';
	}
	else
	{
		theURL = 'http://' + document.location.hostname + '/messages.ashx';
	}

	jQuery.ajax({
		type: 'post',
		url: theURL,
		async: false,
		success: function (response) {
			returnValue = jQuery.parseJSON(response);
		},
		error: function (xhr) {
			returnValue = null;
		}
	});
	return returnValue
}


function rebindValidationRules(s) {
	//define which input names should validate with which functions
	//rules further down have a higher priority (so being required takes highest precidence)
	rules = [
		{ id: ['emailJS', 'fEmailJS', 'ffEmailJS'], func: validateEmail },
		{ id: ['passwordJS'], func: validatePassword },
		{ id: ['postcodeJS', 'hPostcodeJS'], func: validatePostcode },
		{ id: ['dTelJS', 'hTelJS'], func: validatePhone },
		{ id: ['cNumberJS'], func: validateCardNum },
		{ id: ['cIssueJS'], func: validatePosInt },
		{ id: ['cExpiryYearJS'], func: validateExpiryDate },
		{ id: ['cStartYearJS'], func: validateStartDate },
		{ id: ['hAddr1JS', 'hCityJS'], func: validateAddressRequired },
		{ id: ['cNameJS', 'titleJS', 'firstnameJS', 'surnameJS', 'rTitleJS', 'rFNameJS', 'rLNameJS', 'dAddr1JS', 'dCityJS', 'hAddr1JS', 'hCityJS', 'fNameJS', 'ffNameJS'], func: validateRequired }
	];

	//implement the rules
	for (r in rules) {
		var str = '';
		//if a name starts with a special char, we place it before the = sign.
		//this allows us to optionally use jQuery attribute pattern matching
		var prefix = /^[\*\~\$\^\!]/;
		for (n in rules[r].id) {
			var rule = 'id' + (prefix.test(rules[r].id[n]) ? rules[r].id[n].charAt(0) + '=' : '=') + rules[r].id[n].replace(prefix, '');
			str += '*[' + rule + '],';
		}

		jQuery(s).find(str).focus(clearValidation).blur(rules[r].func).each(function () {
			if (jQuery(this).is(':visible') && jQuery(this).val() != '') {
				jQuery(this).triggerHandler('blur');
			}
		});
	}
}


function bindValidationRules(s) {
	//define which input names should validate with which functions
	//rules further down have a higher priority (so being required takes highest precidence)
	rules = [
		{ id: ['emailJS', 'fEmailJS', 'ffEmailJS'], func: validateEmail },
		{ id: ['passwordJS'], func: validatePassword },
		{ id: ['postcodeJS'], func: validatePostcode },
		{ id: ['dTelJS', 'hTelJS'], func: validatePhone },
		{ id: ['cNumberJS'], func: validateCardNum },
		{ id: ['cIssueJS'], func: validatePosInt },
		{ id: ['cExpiryYearJS'], func: validateExpiryDate },
		{ id: ['cStartYearJS'], func: validateStartDate },
		{ id: ['hAddr1JS', 'hCityJS'], func: validateAddressRequired },
		{ id: ['cNameJS', 'titleJS', 'firstnameJS', 'surnameJS', 'rTitleJS', 'rFNameJS', 'rLNameJS', 'dAddr1JS', 'dCityJS', 'hAddr1JS', 'hCityJS', 'hPostcodeJS', 'fNameJS', 'ffNameJS'], func: validateRequired }
	];

	/*
	rules = [
		{ id: ['cNameJS', 'titleJS', 'firstnameJS', 'surnameJS', 'rTitleJS', 'rFNameJS', 'rLNameJS', 'emailJS', 'dAddr1JS', 'dCityJS', 'hAddr1JS', 'hCityJS'], func: validateRequired }

		{ id: ['emailJS', '$DocumentRequestEmail'], func: validateEmail },
		{ id: ['postcodeJS', 'hPostcodeJS', '$DocumentRequestPostcode'], func: validatePostcode },
		{ id: ['dTelJS', 'hTelJS'], func: validatePhone },
		{ id: ['cNumberJS'], func: validateCardNum },
		{ id: ['cExpiryMonthJS', 'cStartMonthJS'], func: validateMonth },
		{ id: ['cExpiryYearJS'], func: validateExpiryDate },
		{ id: ['cStartYearJS'], func: validateStartDate },
		{ id: ['cIssueJS'], func: validatePosInt },
		{ id: ['cNameJS'], func: validateCardName },
		{ id: ['hAddr1JS', 'hCityJS'], func: validateAddressRequired },
		{ id: ['titleJS', 'firstnameJS', 'surnameJS', 'rTitleJS', 'rFNameJS', 'rLNameJS', 'emailJS', 'dAddr1JS', 'dCityJS', 'hAddr1JS', 'hCityJS', 'cExpiryMonthJS', 'cExpiryYearJS', '$DocumentRequestTitle', '$DocumentRequestFirstName', '$DocumentRequestSurname', '$DocumentRequestPhone', '$DocumentRequestAddress', '$DocumentRequestPostcode'], func: validateRequired }
	];
	*/

	//implement the rules
	for (r in rules) {
		var str = '';
		//if a name starts with a special char, we place it before the = sign.
		//this allows us to optionally use jQuery attribute pattern matching
		var prefix = /^[\*\~\$\^\!]/;
		for (n in rules[r].id) {
			var rule = 'id' + (prefix.test(rules[r].id[n]) ? rules[r].id[n].charAt(0) + '=' : '=') + rules[r].id[n].replace(prefix, '');
			str += '*[' + rule + '],';
		}

		jQuery(s).find(str).focus(clearValidation).blur(rules[r].func).each(function () {
			if (jQuery(this).is(':visible') && jQuery(this).val() != '') {
				jQuery(this).triggerHandler('blur');
			}
		});
	}
}


function clearValidation() {
	var dl = jQuery(this)
		.removeClass('invalid').removeClass('valid')
		.closest('dl').removeClass('invalid').removeClass('valid')
		.find('.required').show();
}


//updates the supplied input element to be invalid / not dpeneding on bool(v)
//updates the container to be valid / invalid depending on whether it contains any invalid inputs or not
function updateValidation(e, v, event, default_message, message) {
	//if (jQuery("#posted").val() == 0) {
		jQuery(e).addClass(v ? 'valid' : 'invalid').removeClass(v ? 'invalid' : 'valid');

		var dl = jQuery(e).closest('dl');
		if (dl.find('.invalid').length == 0) {
			dl.removeClass('invalid').addClass('valid');
			dl.find('.required').hide();
			dl.find('dd strong').remove();
			//errorSummary();
		}
		else {
			dl.removeClass('valid').addClass('invalid');
			dl.find('.required').show();

			//remove any previous error message
			if (jQuery(e).parents("dd").find("strong[class=fieldErrorMessage]").length != 0) {
				jQuery(e).parents("dd").find("strong[class=fieldErrorMessage]").remove();
			}

			if (jQuery(e).val() == '') {
				$("<strong class=\"fieldErrorMessage\">" + default_message + "</strong>").insertAfter(jQuery(e).parent("div"));
			}
			else if (!v) {
				$("<strong class=\"fieldErrorMessage\">" + message + "</strong>").insertAfter(jQuery(e).parent("div"));
			}

			//errorSummary();
			//if we fail validation, don't let other rules override
			event.stopImmediatePropagation();
		}
	//}
}


function errorSummary() {
	var invalidDls = $("form dl[class='formPair invalid']");
	var currentDl;
	var label;
	var em;
	var field;
	var errorSummary = "";

	//alert("invalidDls.length: " + invalidDls.length);

	for (i = 0; i < invalidDls.length; i++) {
		currentDl = invalidDls[i];
		label = $(currentDl).find("dt label").html();
		em = ( $(currentDl).find("dt label em").length != 0) ? $(currentDl).find("dt label em").html() : "";
		label = label.replace(em, "");
		field = $(currentDl).find("dd div.fieldWrap").children();
		errorSummary += "<a href=\"#" + $(field).attr("name") + "\">" + label + "</a>, ";
	}

	//alert("errorSummary: " + errorSummary);

	if (errorSummary.length != 0) {
		errorSummary = errorSummary.substring(0, errorSummary.length - 2);
		$("#warningMessage ul").html("<li>The following answers seem to be missing from the form:</li><li>" + errorSummary + "</li>");
		$("#warningMessage").show();
	}
	else {
		$("#warningMessage ul").html("");
		if ($("#warningMessage ul").html() == '') $("#warningMessage").hide();
	}
}


//a non empty field
function validateRequired(e) {
	updateValidation(this, (jQuery(this).val() != ''), e, objJSON.RequiredField, objJSON.RequiredField);
}

//a valid/empty email address
function validateEmail(e) {

	var emailReg = new RegExp(/^((?:(?:(?:[a-zA-Z0-9][\.\-\+_]*)*)))\@((?:(?:(?:[a-zA-Z0-9][\.\-_]?){0,62})[a-zA-Z0-9])+)\.([a-zA-Z0-9]{2,6})$/);
	updateValidation(this, emailReg.test(jQuery(this).val()), e, objJSON.RequiredField, objJSON.EmailField);

/*
	alert((jQuery("#posted") == null || jQuery("#posted").val() == "0"));

	if (jQuery("#posted") == null || jQuery("#posted").val() == "0") {
		alert("here 1");
		var emailReg = new RegExp(/^((?:(?:(?:[a-zA-Z0-9][\.\-\+_]*)*)))\@((?:(?:(?:[a-zA-Z0-9][\.\-_]?){0,62})[a-zA-Z0-9])+)\.([a-zA-Z0-9]{2,6})$/);
		updateValidation(this, emailReg.test(jQuery(this).val()), e, objJSON.RequiredField, objJSON.EmailField);
	}
	else {
		alert("here 2");
		jQuery(this).change(
			function () {
				alert((jQuery("#posted") == null || jQuery("#posted").val() == "0"));
				//jQuery("#posted").val() = "0";
				jQuery("#posted").attr("value", "0");
				//alert("changed");
				alert((jQuery("#posted") == null || jQuery("#posted").val() == "0"));
				validateEmail(this);
			}
		)
		}
	*/
	//var emailReg = new RegExp(/^((?:(?:(?:[a-zA-Z0-9][\.\-\+_]*)*)))\@((?:(?:(?:[a-zA-Z0-9][\.\-_]?){0,62})[a-zA-Z0-9])+)\.([a-zA-Z0-9]{2,6})$/);
	//updateValidation(this, emailReg.test(jQuery(this).val()), e, objJSON.RequiredField, objJSON.EmailField);
}

//length must be over 6 characters
function validatePassword(e) {
	updateValidation(this, (jQuery(this).val() && jQuery(this).val().length >= 6), e, objJSON.RequiredField, objJSON.PasswordField);
}

//a valid postcode, not empty
function validatePostcode(e) {
	var postcodeReg = new RegExp(/^[a-zA-Z][a-zA-Z0-9]{1,3} \d[a-zA-Z]{2}$/);
	updateValidation(this, postcodeReg.test(jQuery(this).val()), e, objJSON.RequiredField, objJSON.PostcodeField);
}

//validates a phone number (optional (+), backets, spaces and at least 9 numbers)
function validatePhone(e) {
	var phoneReg = new RegExp(/^[\d\+\(\\)a-zA-Z\s\-\.]{10,30}$/);
	updateValidation(this, phoneReg.test(jQuery(this).val()), e, objJSON.TelephoneRequiredField, objJSON.TelephoneField);
}

/* Luhn algorithm number checker - (c) 2005-2009 - planzero.org            *
* This code has been released into the public domain, however please      *
* give credit to the original author where possible.                      */
function validateCardNum(e) {
	number = jQuery(this).val();
	if (number.indexOf('****') >= 0) return;
	// Strip any non-digits (useful for credit card numbers with spaces and hyphens)
	var number = number.replace(/\D/g, '');
	// Set the string length and parity
	var number_length = number.length;
	var parity = number_length % 2;
	// Loop through each digit and do the maths
	var total = 0;
	for (i = 0; i < number_length; i++) {
		var digit = number.charAt(i);
		// Multiply alternate digits by two
		if (i % 2 == parity) {
			digit = digit * 2;
			// If the sum is two digits, add them together (in effect)
			if (digit > 9) {
				digit = digit - 9;
			}
		}
		// Total up the digits
		total = total + parseInt(digit);
	}
	// If the total mod 10 equals 0, the number is valid
	updateValidation(this, (number.length > 0 && total % 10 == 0), e, objJSON.RequiredField, objJSON.CreditCardNumberField);
}

/*
//validates a number from 1-12 (empty is valid)
function validateMonth(e) {
	if (jQuery(this).val() != '') {
		var Reg = new RegExp(/^[1-9]{1}$/);

		//fix to auto add a lead 0 to submission if only 1 char is entered for month/year date
		if (jQuery(this).val().length == 1 && Reg.test(jQuery(this).val())) {
			//alert("yo");
			jQuery(this).attr("value", "0" + String(jQuery(this).val()));
		}

		//updateValidation(this, (jQuery(this).val() * 1) > 0 && (jQuery(this).val() * 1) <= 12, e, objJSON.RequiredField, objJSON.MonthField);
		//validateExpiryDate(jQuery("#cExpiryYear"))

		if (jQuery(this).attr("name") == "cExpiryMonth") {
			validateExpiryDate(jQuery("#cExpiryYear").blur());
		}
		else if (jQuery(this).attr("name") == "cStartMonth") {
			validateExpiryDate(jQuery("#cStartYear").blur());
		}
		//validateExpiryDate(e);
	}
}
*/

/*
function validateYear(field) {
	//alert(field);
	//alert(field.val());

	if (field.val() != '') {
		var Reg = new RegExp(/^[1-9]{1}$/);

		//fix to auto add a lead 0 to submission if only 1 char is entered for month/year date
		if (field.val().length == 1 && Reg.test(field.val())) {
			//alert("yo");
			field.attr("value", "0" + String(field.val()));
		}
	}
}
*/

//validates an expiry date (must be > today and > startdate)
function validateExpiryDate(e) {
	var d = new Date();
	var myDate = new Date();
	var startDate = new Date();

	//validateYear(jQuery(this));

	var validate;
	try {
		if (jQuery("#cStartMonthJS").val() != "" && jQuery("#cStartYearJS").val() != "") {
			startDate.setFullYear("20" + jQuery("#cStartYearJS").val(), jQuery("#cStartMonthJS").val() - 1, "01");
			//alert("startDate: " + startDate);

			myDate.setFullYear("20" + jQuery(this).val(), jQuery("#cExpiryMonthJS").val() - 1, "01");
			//alert("myDate: " + myDate);

			validate = (myDate > d && myDate > startDate);
		}
		else {
			myDate.setFullYear("20" + jQuery(this).val(), jQuery("#cExpiryMonthJS").val() - 1, "01");

			//alert("myDate: " + myDate);
			//alert("d: " + d);
			validate = (myDate > d);
		}
	}
	catch (err) {
		validate = false;
	}

	//alert("validate: " + validate);

	jQuery("#cExpiryMonthJS").addClass(validate ? 'valid' : 'invalid').removeClass(validate ? 'invalid' : 'valid');

	updateValidation(this, validate, e, objJSON.RequiredField, objJSON.CreditCardExpiryDateField);
}

//validates a start date (must be < today and < expirydate)
function validateStartDate(e) {
	var d = new Date();
	var thisYear = d.getFullYear();
	var myDate = new Date();
	var expiryDate = new Date();

	var validate;
	try {
		if (jQuery("#cExpiryMonthJS").val() != "" && jQuery("#cExpiryYearJS").val() != "") {
			expiryDate.setFullYear("20" + jQuery("#cExpiryYearJS").val(), jQuery("#cExpiryMonthJS").val() - 1, "01");
			//alert("expiryDate: " + expiryDate);

			myDate.setFullYear("20" + jQuery(this).val(), jQuery("#cStartMonthJS").val() - 1, "01");
			validate = (myDate < d && myDate < expiryDate);
		}
		else {
			if (jQuery("#cStartMonthJS").val() != "" && jQuery("#cStartYearJS").val() != "") {
				myDate.setFullYear("20" + jQuery(this).val(), jQuery("#cStartMonthJS").val() - 1, "01");
				validate = (myDate < d);
			}
			else {
				validate = true;
			}
		}
	}
	catch (err) {
		validate = false;
	}

	jQuery("#cStartMonthJS").addClass(validate ? 'valid' : 'invalid').removeClass(validate ? 'invalid' : 'valid');

	if (jQuery(this).val() != '') updateValidation(this, validate, e, objJSON.RequiredField, objJSON.CreditCardStartDateField);
}

//validates the name on a credit card
function validateCardName(e) {
	updateValidation(this, (jQuery(this).val() != ''), e, objJSON.CreditCardNameField, objJSON.CreditCardNameField);
}

//validates the address on a credit card
function validateAddressRequired(e) {
	updateValidation(this, (jQuery(this).val() != ''), e, objJSON.CreditCardAddressRequiredField, objJSON.CreditCardAddressRequiredField);
}

//validates  positive integer
function validatePosInt(e) {
	if (jQuery(this).val() != '') updateValidation(this, (jQuery(this).val() * 1) > 0, e, objJSON.CreditCardIssueNumberField, objJSON.CreditCardIssueNumberField);
}