(function () {
	var window = this,
		$ = window.jQuery,
		required = {},
		i = 0,
		j = 0,
		getLabelName = function (fieldName) {
			return fieldName.replace(/^_custom=[^=]+=[^=]+=/g, '')
				.replace(/\.(\w)/g, function (m, p1, o, s) {
				return p1.toUpperCase();
			});
		},
		setRequired = function (formId) {
			for (i = 0; i < required[formId].length; i++) {
				for (var fieldName in required[formId][i]) {
					$('#' + formId + ' .' + getLabelName(fieldName))
						.addClass('required')
						.children('span:lt(2)')
						.prepend('<em>*</em>');
				}
			}
		},
		fieldsMsg = function (fRef, fields, msg) {
			var etxt = '';
			for (i = 0; i < fields.length; i++) {
				etxt += ((i === 0) ?
					'<strong>' + msg + ':</strong> ' :
					', ') + '<span>' + fields[i][1] + '</span>';
				$('.' + getLabelName(fields[i][0]), fRef)
					.find('input,textarea,select').addClass('baddata');
			}
			return etxt;
		},
		// boolean helper functions
		isSSN = function (ssnObj) {
			var ssnTest = /^(?!000)([0-6]\d{2}|7([0-6]\d|7[012]))([ \-]?)(?!00)\d\d\3(?!0000)\d{4}$/,
				quickSinTest = /^\d{3}\-?\d{3}\-?\d{3}$/,
				quickEidTest = /^\d{2}([ \-]?)\d{7}$/;
			return (ssnTest.test(ssnObj.value) ||
				quickSinTest.test(ssnObj.value) ||
				quickEidTest.test(ssnObj.value));
		},
		isEmail = function (elm) {
			return (/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/).test(elm.value);
		},
		isMileage = function (elm) {
			var validMileage = /([\d|,]+).*/;
			if (validMileage.test(elm.value)) {
				elm.value = elm.value.replace(validMileage, '$1');
				return true;
			} else {
				return false;
			}
		},
		isYear = function (elm) {
			var validYear = /[\d]{4}/;
			if (validYear.test(elm.value)) {
				return true;
			} else {
				return false;
			}
		},
		isPhoneNumber = function (elm) {
			var phoneNumberTest = /^(?:(?:\+?1\s*(?:[.\-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.\-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.\-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/;
			return phoneNumberTest.test(elm.value);
		},
		isDate = function (elm) {
			var dateTest = /^((((0?[13578])|(1[02]))[\/|\-]?((0?[1-9]|[0-2][0-9])|(3[01])))|(((0?[469])|(11))[\/|\-]?((0?[1-9]|[0-2][0-9])|(30)))|(0?[2][\/\-]?(0?[1-9]|[0-2][0-9])))[\/\-]?\d{2,4}$/;
			return dateTest.test(elm.value);
		},
		isVin = function (elm) {
			return (elm.value.length === 17);
		},
		isPostalCode = function (elm) {
			// matches 05401, 05401-2035, G8H 7B5
			var postalCodeTest = /^((\d{5}-\d{4})|(\d{5})|([a-zA-Z]\d[a-zA-Z](\s)?\d[a-zA-Z]\d))$/;
			return postalCodeTest.test(elm.value);
		},
		validate = function (formRef, fstart, fstop, callback) {
			var missingfields = [],
				badfields = [],
				errortext = '',
				oRef,
				oLabel,
				fieldName,
				radioChecked = false;
		
			// check all fieldsets if wizard-style validation is not used
			if (!fstart) {
				fstart = 0;
			}
			if (!fstop) {
				fstop = required[formRef.id].length;
			}

			$('.formerrors:visible', formRef).fadeOut();
			$('.baddata', formRef).removeClass('baddata');
		
			// following milage data check added in response to DNA687953
			if (($('input[name=mileage]')[0] !== undefined) &&
				($('input[name=mileage]').val().length > 6)) {
				badfields.push(['', $('label.mileage span')
					.text().replace('*', '')]);
			}

			for (i = fstart; i < fstop; i++) {
				for (fieldName in required[formRef.id][i]) {
					oRef = formRef.elements[fieldName];
					oLabel = required[formRef.id][i][fieldName];
				
					// radio buttons
					if ((oRef.length) && (oRef[0].type === 'radio')) {
						radioChecked = false;
						for (j = 0; j < oRef.length; j++) {
							if (oRef[j].checked) {
								radioChecked = true;
								break;
							}
						}
						if (!radioChecked) {
							missingfields.push([fieldName, oLabel]);
						}
					} else if (!$.trim(oRef.value)) {
						missingfields.push([fieldName, oLabel]);
					} else if (fieldName.toLowerCase().indexOf("email") > -1) {
						if (!isEmail(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.toLowerCase().indexOf("phone") > -1) {
						if (!isPhoneNumber(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.indexOf(".postalCode") > -1) {
						if (!isPostalCode(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.indexOf(".dob") > -1) {
						if (!isDate(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.toLowerCase()
						.indexOf("contact.password") > -1) {
						if (formRef.elements['contact.password']
							.value !==
							formRef.elements['contact.passwordConfirm']
							.value) {
							badfields.push([fieldName, oLabel]);
						}
					} else if ((fieldName === "accountId") && (oRef.options)) {
						// allow default value for non-required fields
						if (!oRef.selectedIndex && !oRef.options[0].text) {
							missingfields.push([fieldName, oLabel]);
						}
					} else if (fieldName === "year") {
						if (!isYear(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName === "mileage") {
						if (!isMileage(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.toLowerCase()
						.indexOf("applicant.ssn") > -1 ||
						fieldName.toLowerCase()
							.indexOf("applicant.sin") > -1) {
						if (!isSSN(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					} else if (fieldName.toLowerCase().indexOf("vin") !== -1) {
						if (!isVin(oRef)) {
							badfields.push([fieldName, oLabel]);
						}
					}
				}
			}

			if ((missingfields.length > 0) || (badfields.length > 0)) {
				// DNA327658
				if (badfields.length && badfields[0][0]) {
					$('[name=' + badfields[0][0] + ']', formRef).focus();
				} else if (missingfields.length && missingfields[0][0]) {
					$('[name=' + missingfields[0][0] + ']', formRef).focus();
				}
				errortext += fieldsMsg(formRef,
					missingfields,
					required.missingMsg);
				if ((missingfields.length > 0) && (badfields.length > 0)) {
					errortext += '<br /><br />';
				}
				errortext += fieldsMsg(formRef,
					badfields,
					required.baddataMsg);
				$(formRef).find('.formerrors').html(errortext).fadeIn();
				if (callback && callback.ifFalse) {
					callback.ifFalse();
				}
				if ($.fn.ScrollTo) {
					$.scrollTo($(formRef), '1000');
				}
			} else {
				if (callback && callback.ifTrue) {
					callback.ifTrue();
				}
				if (formRef.id === "directions" &&
					window.submitDirections) {
					//used only by the directions form on the directions page
					window.submitDirections(formRef);
				} else {
					$('.submit a', formRef).css({
						opacity: 0.25
					}).unbind('click').click(function () {
						return false;
					});
					formRef.submit();
				}
			}
		};
	
	window.required = required;
	window.i = i;
	window.j = j;
	window.getLabelName = getLabelName;
	window.setRequired = setRequired;
	window.fieldsMsg = fieldsMsg;
	window.isSSN = isSSN;
	window.isEmail = isEmail;
	window.isMileage = isMileage;
	window.isYear = isYear;
	window.isPhoneNumber = isPhoneNumber;
	window.isDate = isDate;
	window.isVin = isVin;
	window.isPostalCode = isPostalCode;
	window.validate = validate;
}());
