
fieldLabels = {
		'visitDate': "Date Visiting",
		'arrival': "Time of Arrival",
		'departure': "Time of Departure",
		'contact': "Contact Person",
		'groupname': "Name of Group",
		'address': "Address",
		'city': "City",
		'state': "State",
		'zip': "Zip",
		'phone': "Phone",
		'grouptype': "Type of Group",
		'studentcount': "Number of participants/students",
		'adultcount': "Number of Adults/Chaparones",
		'totalvisitors': "Total Number of Visitors",
		'contactemail': "Email Address",
		'studentgrade': "Student Grade",
		'otherarea': "Other area you will be visiting",
		'brochureOptIn': "Check to join the mailing list",
		'comments': "Additional comments or questions",
		'buscount': "Expected Number of Busses"
};

fieldLimits = {
		'contact': 100,
		'groupname': 100,
		'address': 200,
		'city': 100,
		'zip': 12,
		'phone': 20,
		'grouptype': 200,
		'contactemail': 200,
		'otherarea': 100,
		'comments': 4000
};

dateFields = [
		'visitDate'
];

timeFields = [
		'arrival',
		'departure'
];

numberFields = [
		'studentcount',
		'adultcount',
		'totalvisitors',
		'buscount'
];

requiredFields = [
  		'visitDate',
  		'arrival',
  		'departure',
  		'contact',
  		'groupname',
  		'address',
  		'city',
  		'state',
  		'zip',
  		'phone',
  		'grouptype',
  		'studentcount',
  		'adultcount',
  		'totalvisitors',
  		'contactemail'
];

function validateForm(theForm)
{
	if(!theForm) { return false; }
	return _checkRequired(theForm) 
	    && _checkLimits(theForm)
	    && _checkNumbers(theForm)
	    && _checkDates(theForm) 
	    && _checkTimes(theForm)
	    && _clearErrorFields(theForm)
	    && _confirmSubmit(); 
}

function _checkRequired(theForm)
{
	if(!theForm) { return false; }
	var missingFields = new Array();
	var err_start = "The following fields are required, and cannot be empty:\n\n";
	for(var i=0; i<requiredFields.length; i++)
	{
		if(theForm[requiredFields[i]].value == "") {
			missingFields[missingFields.length] = requiredFields[i];
			theForm[requiredFields[i]].setAttribute("class", "invalid");
		}
		else 
			theForm[requiredFields[i]].removeAttribute("class");
	}
	
	var msg = "";
	for(i=0; i<missingFields.length; i++)
	{
		msg += (fieldLabels[missingFields[i]] + "\n");
	}
	
	if(msg != "")
	{
		alert(err_start + msg);
		theForm[missingFields[0]].focus();
		return false;
	}

	return true;
}

function _checkLimits(theForm)
{
	if(!theForm) { return false; }
	var toobigFields = new Array();
	var err_start = "The following fields are too large:\n\n";
	
	for(item in fieldLimits)
	{	
		if(theForm[item].value != "")
		{
			theForm[item].value = trim(theForm[item].value);
			if(theForm[item].value.length > fieldLimits[item]) 
			{
				theForm[item].setAttribute("class", "invalid");
				toobigFields[toobigFields.length] = item;
			}
			else 
				theForm[item].removeAttribute("class");
		}
	}
	
	var msg = "";
	for(var i=0; i<toobigFields.length; i++)
	{   
		msg += (fieldLabels[toobigFields[i]] + " must be less than " 
				+ fieldLimits[toobigFields[i]] + " characters.\n");
		if(toobigFields[i] == "state")
			msg += "(Use your state's 2-letter abbreviation)\n";
	}
	
	if(msg != "")
	{
		alert(err_start + msg);
		theForm[toobigFields[0]].focus();
		return false;
	}

	return true;
}

function _checkDates(theForm)
{
	if(!theForm) { return false; }
	
	var badFields = new Array();
	for(var i=0; i<dateFields.length; i++)
	{
		if(theForm[dateFields[i]].value != "")
		{
			var pDate = parseDate(theForm[dateFields[i]].value);
			if(pDate=="")
			{
				theForm[dateFields[i]].setAttribute("class", "invalid");
				badFields[badFields.length] = dateFields[i];
			}
			else
			{
				theForm[dateFields[i]].removeAttribute("class");
				theForm[dateFields[i]].value = pDate;
			}
		}
	}
	
	var msg = "";
	for(i=0; i<badFields.length; i++)
	{
		msg += (fieldLabels[badFields[i]] + " is not a valid date.\n");
	}
	
	if(msg != "")
	{
		alert(msg + "(Use the format 'dd/mm/yy').");
		theForm[badFields[0]].focus();
		return false;
	}
	
	return true;
}

function _checkTimes(theForm)
{
	if(!theForm) { return false; }
	
	var badFields = new Array();
	for(var i=0; i<timeFields.length; i++)
	{
		if(theForm[timeFields[i]].value != "")
		{
			var pTime = parseTime(theForm[timeFields[i]].value);
			if(pTime=="")
			{
				theForm[timeFields[i]].setAttribute("class", "invalid");
				badFields[badFields.length] = timeFields[i];
			}
			else
			{
				theForm[timeFields[i]].removeAttribute("class");
				theForm[timeFields[i]].value = pTime;
			}
		}
	}
	
	var msg = "";
	for(i=0; i<badFields.length; i++)
	{
		msg += (fieldLabels[badFields[i]] + " is not a valid time.\n");
	}
	
	if(msg != "")
	{
		alert(msg + "(Use the format 'HH:MM am').");
		theForm[badFields[0]].focus();
		return false;
	}
	
	return true;
}

function _checkNumbers(theForm)
{
	if(!theForm) { return false; }
	var nanFields = new Array();
	var toobigFields = new Array();
	var err_start = "The following fields require valid numbers:\n\n";
	for(var i=0; i<numberFields.length; i++)
	{
		if(isNaN(theForm[numberFields[i]].value))
		{
			theForm[numberFields[i]].setAttribute("class", "invalid");
			nanFields[nanFields.length] = numberFields[i];
		}
		// all number fields (other than 1/0) are limited to 3 digits
		else
		{
			if(theForm[numberFields[i]].value < 0)
				theForm[numberFields[i]].value = Math.abs(theForm[numberFields[i]].value);
			// new 'if' statement
			if(theForm[numberFields[i]].value > 999)
			{
				theForm[numberFields[i]].setAttribute("class", "invalid");
				toobigFields[toobigFields.length] = numberFields[i];				
			}
			else 
				theForm[numberFields[i]].removeAttribute("class");
		}
	}
	
	var msgNaN = "";
	for(i=0; i<nanFields.length; i++)
	{
		msgNaN += (fieldLabels[nanFields[i]] + " must be a valid number.\n");
	}
	
	var msgBig = "";
	for(i=0; i<toobigFields.length; i++)
	{
		msgBig += (fieldLabels[toobigFields[i]] + " must be less than 999.\n");
	}
	
	if(msgNaN != "" && msgBig != "")
	{
		alert(err_start + msgNaN + "\n\nAdditionally, \n");
		theForm[nanFields[0]].focus();
		return false;			
	}
	else
	{
		if(msgNaN != "")
		{
			alert(err_start + msgNaN);
			theForm[nanFields[0]].focus();
			return false;
		}
		else if(msgBig != "")
		{
			alert(msgBig);
			theForm[toobigFields[0]].focus();
			return false;
		}
	}
	
    return true;
}

function _confirmSubmit(theForm)
{
	if(!confirm("Input validation successful.  Continue?"))
		return false;
	else
		return true;
}

function _clearErrorFields(theForm)
{
	for(item in fieldLabels)
	{
		if(theForm[item].hasAttribute("class") 
				&& theForm[item].getAttribute("class") == "invalid")
		{
			theForm[item].removeAttribute("class");
		}
	}
	return true;
}

function parseDate(dateStr)
{
	if(dateStr == "") { return dateStr; }
	var datePattern = /(\d{1,2})([\.\:\/\-])(\d{1,2})\2(\d{2,4})/;
	var result = dateStr.match(datePattern);
	
	if(result && result.length == 5)
	{
		var p1 = result[1]; var p2 = result[3]; var p3 = result[4];
		var m = (p1 >= 1 && p1 <= 12) ? p1 : (p2 >= 1 && p2 <= 12) ? p2 : Number.NaN;
		var d = (p2 >= 1 && p2 <= 31) ? p2 : (isNaN(m) && p1 >=1 && p1 <= 31) ? p1 : Number.NaN;
		if(isNaN(m) && d == p1 && (p2 >= 1 && p2 <= 12) ) { m = p2; }
		
		// we can be easy with the year - nothing is retro-active, so we start at 2009.
		// WARNING!  This will break in 2100!!!
		var date = new Date();
		var currYear = date.getFullYear();
		var y = (p3.length == 4 && p3 >= (currYear-1) && p3 <= (currYear+2))
			? (p3-2000) : (p3.length == 2 && p3 >= (currYear-2001) && p3 <= (currYear-1998))
				? p3 : Number.NaN;
		if(isNaN(m) || isNaN(d) || isNaN(y))
			return "";
		
		return twoDigitNumber(m)+"/"+twoDigitNumber(d)+"/"+twoDigitNumber(y);
	}
	return "";

}

function parseTime(timeStr)
{
	if(timeStr == "") return timeStr;
	var timePattern = /(\d{1,2})\:(\d{1,2})\s*([ap])\.?m\.?/i;
	var result = timeStr.match(timePattern);
	if(result && result.length == 4)
	{
		var p1 = result[1]; var p2 = result[2]; var p3 = result[3];
		var h = (p1 >= 1 && p1 <= 12) ? p1 : (p1 == 0) 
				? 12 : (p1 >= 13 && p1 < 24) ? p1 - 12 : Number.NaN;
		var m = (p2 >= 0 && p2 < 60) ? p2 : Number.NaN;
		var a = ((p1 > 12 && p1 < 24) || p1 == 0) ? "pm" : p3.toLowerCase() + "m";
		if(isNaN(h) || isNaN(m))
			return "";
		return h + ":" + twoDigitNumber(m) + " " + a;
	}
	return "";
}

function twoDigitNumber(num)
{
	if(isNaN(num)) return "00";
	if(num < 0) num = Math.abs(num);
	if(num.toString().length == 2) return num.toString();
	if(num == 0) return "00";
	if(num<10) return "0"+Number(num);
	if(num>100) return (num.toString()).substring((num.toString()).length-2);
	return num.toString();
}

function trim(stringToTrim) 
{
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}

function ltrim(stringToTrim) 
{
	return stringToTrim.replace(/^\s+/,"");
}

function rtrim(stringToTrim) 
{
	return stringToTrim.replace(/\s+$/,"");
}



