var vinToolSelector = '.vinFormField';
var underlineSelector = '#underline';
var consoleSelector = '#console';

//^(([a-h,A-H,j-n,J-N,p,P,s-z,S-Z,0-9]{8})([x,X,0-9])([a-h,A-H,j-n,J-N,p,P,s-z,S-Z,0-9]{3})(\\d{5}))$

//using 'true' b/c an empty character (not the same as a space) should not indicate an incorrectly typed character.
var vinFlags = new Array(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);

//3 regular expressions used to validate vin # format.
var reg1 = new RegExp('[a-hA-Hj-nJ-NpPrRs-zS-Z0-9]');
var reg2 = new RegExp('[xX0-9]');
var reg3 = new RegExp('[0-9]');

/** Exclude the following key press events
* 8:	Backspace
* 9:	Tab
* 13:   Enter
* 16:	Shift
* 17:	Ctrl
* 18:	Alt
* 19:	Pause Break
* 20:	Caps Lock
* 27:	Esc
* 33:	Page Up
* 34:	Page Down
* 35:	End
* 36:	Home
* 37:	Left Arrow
* 38:	Up Arrow
* 39:	Right Arrow
* 40:	Down Arrow
* 45:	Insert
* 46:	Delete
* 144:	Num Lock
* 145:	Scroll Lock
*/
var keys = [9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 144, 145];

//Check Sum Values
var strWeight = [8, 7, 6, 5, 4, 3, 2, 10, -1, 9, 8, 7, 6, 5, 4, 3, 2];
var FormulaValue = new Array()
FormulaValue["A"] = 1;
FormulaValue["B"] = 2;
FormulaValue["C"] = 3;
FormulaValue["D"] = 4;
FormulaValue["E"] = 5;
FormulaValue["F"] = 6;
FormulaValue["G"] = 7;
FormulaValue["H"] = 8;
FormulaValue["I"] = 9;
FormulaValue["J"] = 1;
FormulaValue["K"] = 2;
FormulaValue["L"] = 3;
FormulaValue["M"] = 4;
FormulaValue["N"] = 5;
FormulaValue["O"] = 6;
FormulaValue["P"] = 7;
FormulaValue["Q"] = 8;
FormulaValue["R"] = 9;
FormulaValue["S"] = 2;
FormulaValue["T"] = 3;
FormulaValue["U"] = 4;
FormulaValue["V"] = 5;
FormulaValue["W"] = 6;
FormulaValue["X"] = 7;
FormulaValue["Y"] = 8;
FormulaValue["Z"] = 9;
FormulaValue["0"] = 0;
FormulaValue["1"] = 1;
FormulaValue["2"] = 2;
FormulaValue["3"] = 3;
FormulaValue["4"] = 4;
FormulaValue["5"] = 5;
FormulaValue["6"] = 6;
FormulaValue["7"] = 7;
FormulaValue["8"] = 8;
FormulaValue["9"] = 9;

function checkVin() {
	var strVin = $(vinToolSelector).val().toUpperCase();
	var strCheckDigit = '';
	var strResult = 0;
	if (strVin.length == 17)
	{
		for (var i = 0; i < 17; i++) {
			var tempValue = strVin.substring(i, i + 1);
			if (i == 8) //9th position
			{
				strCheckDigit = tempValue;
			} else {
				strResult += FormulaValue[tempValue] * strWeight[i];
			}
		}
		//alert("Results Sum: " + strResult + " Check digit:" + strCheckDigit + " Result:" + (strResult % 11))

		if (strCheckDigit == 'X')
		{
			return (strResult % 11 == 10) ? true : false;
		} else {
			return (strResult % 11 == parseInt(strCheckDigit)) ? true : false;
		}

	} else {
		return false;
	}
}


function updateErrorMessages() {

	//Reset all error messages and underlines
	for (var x = 0; x < 17; x++) {
		$(underlineSelector + (x + 1)).css("visibility","hidden");
	}
	$(consoleSelector).html('');
	var InvalidCharacters = new Array(); //Contains a collection of the incorrectly typed characters and used for the error message.
	
	//ErrorArray contains which character positions in the VIN number are invalid
	var ErrorArray = new Array();
	for (var i = 0; i < vinFlags.length; i++) {
		if (vinFlags[i] == false)
			ErrorArray.push(i);
	}
	if (ErrorArray.length > 0) {

		var DisplayLastFive = false; //Flag indicating whether to display this error message.
		for (var x = 0; x < ErrorArray.length; x++) {
			$(underlineSelector + (ErrorArray[x] + 1)).css("visibility","visible"); //Show the appropriate underline
			//Based on the character position, different error messages are generated
			if (ErrorArray[x] < 8) {
				if ($.inArray($(vinToolSelector).val().substring(ErrorArray[x], ErrorArray[x] + 1).toUpperCase(), InvalidCharacters) == -1)
					InvalidCharacters.push($(vinToolSelector).val().substring(ErrorArray[x], ErrorArray[x] + 1).toUpperCase());
			} else if (ErrorArray[x] >= 8 && ErrorArray[x] < 9) {
				$(consoleSelector).append('<p>Sorry, position 9 of the VIN must be a number or the letter X.</p> ');
			} else if (ErrorArray[x] >= 9 && ErrorArray[x] < 12) {
			if ($.inArray($(vinToolSelector).val().substring(ErrorArray[x], ErrorArray[x] + 1).toUpperCase(), InvalidCharacters) == -1)
				InvalidCharacters.push($(vinToolSelector).val().substring(ErrorArray[x], ErrorArray[x] + 1).toUpperCase());
			} else if (ErrorArray[x] >= 12 && ErrorArray[x] < 17) {
				DisplayLastFive = true;
			}
		}
		//Determines if these error messages should be displayed.
		if (InvalidCharacters.length > 0) {
		    $(consoleSelector).append('<p>Sorry, ' + (InvalidCharacters.join(', ')) + ' ' + ((InvalidCharacters.length > 1) ? 'are' : 'is') + ' not a valid VIN character' + ((InvalidCharacters.length > 1) ? 's' : '') + '. </p>');
		}
		if (DisplayLastFive)
		    $(consoleSelector).append('<p>Sorry, the last five positions of the VIN must be numbers.</p> ');
	} 

	if ($(vinToolSelector).val().length == 17)
	{
		if (!checkVin())
		{
			$(consoleSelector).append('<p>Sorry, the VIN number you have entered is invalid.</p> ');
		}
	}
	
}

function validateVinOnSubmit() {

	if (!checkVin() || $(vinToolSelector).val().length != 17)
	{
		$(consoleSelector).append('<p>Sorry, the VIN number you have entered is invalid.</p> ');
		return false;
	} else {
		return true;
	}

}

function setVinFlags() {

	//This method iterates through each character in the VIN number, and based on the character position,
	//A regular expression is applied to determine if the value is valid.
	//vinFlags hold a true/false value for all 17 character positions.

	var strVin = $(vinToolSelector).val();

		//reset all flags to false
		vinFlags = new Array(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);

		for (var x = 0; x < strVin.length; x++) {
			var s = strVin.substring(x, x + 1);

			if (x < 8) {
				vinFlags[x] = (s.match(reg1)) ? true : false;
			} else if (x >= 8 && x < 9) {
				vinFlags[x] = (s.match(reg2)) ? true : false;
			} else if (x >= 9 && x < 12) {
				vinFlags[x] = (s.match(reg1)) ? true : false;
			} else if (x >= 12 && x < 17) {
				vinFlags[x] = (s.match(reg3)) ? true : false;
			}
		}

		updateErrorMessages();
}

$(function() {
	$(vinToolSelector).keyup(function(e) {
		if ($.inArray(e.which, keys) == -1 ) { //&& $(vinToolSelector).val().length > 0) {
			setVinFlags();
		}
	});
});

$(function() {
	$(vinToolSelector).blur(function(e) {
		setVinFlags();
	});
});
