function Verification(fields)
{
	this.fields = fields;			
}

Verification.prototype =
{
	verifyEmail : function (email)
	{
		var reEmail = /^(?:\w+\.?)*\w+@(?:\w+\.)*\w+$/;
		return reEmail.test(email);
	},
	
	verifyHttpUrl : function (url)
	{
		var reHttpUrl = /^http:\/\/(([a-zA-Z0-9-]+\.)+[a-zA-Z][a-zA-Z0-9-]*|([0-9]+\.){3}[0-9]+)(\/.*(\?.*)?)?$/;
		return reHttpUrl.test(url);
	},
	
	verifyUKPostCode : function (postCode)
	{
		var rePostCode = /^[a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]?( [0-9][a-zA-Z]{2,2})?$/;
		return rePostCode.test(postCode);
	},
	
	verifyYear : function (year)
	{
		return ((year >= 0 && year <= 99) || (year >= 1850 && year <= 2100));
	},
	
	verifyNumeric : function (range, num)
	{
		var reNumber = /^\d*$/;
		if (!reNumber.test(num))
			return false;
		else
			return (range == true || (range[0] <= num && num <= range[1]));
	},
	
	luhnCheckSum : function (sCardNum)
	{
		var iOddSum = 0;
		var iEvenSum = 0;
		var bIsOdd = true;

		for (var i = sCardNum.length - 1; i >= 0; i--)
		{
			var iNum = parseInt(sCardNum.charAt(i));
			if (bIsOdd)
				iOddSum += iNum;
			else
				if (iNum + iNum > 9)
					iEvenSum += iNum + iNum - 9
				else
					iEvenSum += iNum + iNum;
			
			bIsOdd = !bIsOdd;
		}

		return ((iEvenSum + iOddSum) % 10 == 0);
	},
	
	cardTypeCheck : function (cardType, cardNum)
	{
		var reType;
		if (cardType.value)
		{
			switch (cardType.value)
			{
				case "Visa":
					reType = /^4\d{12}(\d{3})?$/;
					break;
				case "Mastercard":
					reType = /^5[1-5]\d{14}$/;
					break;
				case "Amex":
					reType = /^3[47]\d{13}$/;
					break;
				case "JCB":
					reType = /^(3\d{15}|2131\d{11}|1800\d{11})$/;
					break;
				case "Switch/Maestro":
					reType = /^((5641|6331|4905)\d{12}|67596[43]\d{10}|67594\d{13}|49(03|11)\d{14}|(6333|4936)\d{15}|6759[50]\d{14}|675960\d{13})$/;
					break;
				default:
					return true;
			}
			return reType.test(cardNum);
		}
		return true;	
	},
	
	errorReport : function ()
	{
		var field;
		var val;
		var rep = "";
		var msg;
		var wasOK;
		for (var idx = 0; idx < this.fields.length; idx++)
		{
			field = this.fields[idx];
			msg = "";
			
			if (field.condition)
			{
				if (!field.condition())
					rep += field.message + "\n";
				continue;
			}
			
			if (!field.control)
				throw "missing control in validation";
			
			if (field.control.disabled)
				continue;
			
			if (field.control.type)
			{
				if (field.control.type == "radio")
				{
					val = "";
					var controls = document.getElementsByName(field.control.name);
					for (var idx2=0; idx2<controls.length; idx2++)
						if (controls[idx2].checked)
							val = controls[idx2].value;
				}
				else
					val = field.control.checked || field.control.value;
			}
			else
				throw field.control + " inappropriate control for validation";
				
			wasOK = (rep == "");
			if (field.required)
			{
				if (val == "")
					msg = "Please enter " + field.desc + ".\n";
			}
			else if (field.mustCheck)
			{
				if (val != true)
					msg = "You must click " + field.desc + ".\n";
			}
			
			if (val != "")
			{
				if (field.email)
				{
					if (!this.verifyEmail(val))
						msg = "Please enter a valid email address for " + field.desc + "\n";
				}
				else if (field.web)
				{
					if (!this.verifyHttpUrl(val))
						msg = "Please enter a valid web address for " + field.desc + "\n";
				}
				else if (field.cardNumber)
				{
					var num = val.replace(/[ -]/g, "");
					if (!this.luhnCheckSum(num))
						msg = "Please enter a valid card number for " + field.desc + "\n";
					else
					{
						if (field.cardType)
							if (!this.cardTypeCheck(field.cardType, num))
								msg = "Please enter an appropriate card number for the card type for " + field.desc + "\n";
					}				
				}
				else if (field.postCode)
				{
					if (!this.verifyUKPostCode(val))
						msg = "Please enter a valid UK post code for " + field.desc + "\n";
				}
				else if (field.numeric)
				{
					if (!this.verifyNumeric(field.numeric, val))
					{
						msg = "Please enter a number for " + field.desc;
						if (field.numeric == true)
							msg += "\n";
						else
							msg += " between " + field.desc[0] + " and " + field.desc[1];
					}
				}
				else if (field.year)
				{
					if (!this.verifyYear(val))
						msg = "Please enter a valid year for " + field.desc + "\n";
				}
				else if (field.match)
				{
					if (!field.match.test(val))
						msg = "Please enter " + field.desc + " in a valid format\n";
				}
			}

			if (msg != "")
			{
				rep += msg;
				if (wasOK) field.control.focus();
			}
		}
		return rep;
	},

	check : function (win)
	{
		var report = this.errorReport();
		if (report != "")
		{
			win.alert(report);
			return false;
		}
		else
			return true;
	}
}


