//array keys are field IDs to be checked for input
//all characters in the string must be low-case, except for field IDs
//there must be exactly only one space between field definition
//event: on which event does the error checking has to take place. can be more than one, separated by /: click, blur, change, etc according to standard javascript, but without the 'on'
//required: whether this field must be non-empty: yes, no
//length: minimum and maximum number of characters in the field: any non-negative number
//type: kind of input checks that must be perfomred: general, alphabet_only, alphanumeric, numeric, positive_numeric, date, turing
//match: whether this field's value must match another field's: fill in with the other field's ID
//nospace: whether the input must not contain space: yes no
InputValidator = {};

InputValidator.CheckDef = {};

InputValidator.DateSeparator = '/';
InputValidator.DateFormat = 'm/d/Y';

InputValidator.IsDateValid = function(ADate,AMonth,AYear) {
	MonthsArr = new Array('','jan','feb','mar','apr','may','jun','jul','agt','sep','oct','nov','dec');
	EoMArr = new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
//	TheDate = ADate.split(InputValidator.DateSeparator);
//	if (TheDate.length == 3) {
//		switch (InputValidator.DateFormat) {
//			case 'm/d/Y' : //e.g. 05/31/2008
//				Day = TheDate[1]; Month = TheDate[0]; Year = TheDate[2];
//				break;
//			case 'M/d/Y' : //e.g. May/31/2008
//				Day = TheDate[1]; Month = MonthsArr[TheDate[0].toLowerCase()]; Year = TheDate[2];
//				break;
//			case 'd/m/Y' : //e.g. 31/05/2008
//				Day = TheDate[0]; Month = TheDate[1]; Year = TheDate[2];
//				break;
//			case 'd/M/Y' : //e.g. 31/May/2008
//				Day = TheDate[0]; Month = MonthsArr[TheDate[1].toLowerCase()]; Year = TheDate[2];
//				break;
//			default :
//				Day = TheDate[1]; Month = TheDate[0]; Year = TheDate[2];
//		}
		if (typeof ADate == 'string') {
			if (ADate.charAt(0) == '0') {
				ADate = ADate.substr(1);
			}
		}
		if (typeof AMonth == 'string') {
			if (AMonth.charAt(0) == '0') {
				AMonth = AMonth.substr(1);
			}
		}
		ADate = parseInt(ADate); AMonth = parseInt(AMonth); AYear = parseInt(AYear);
		EoMArr[2] = (AYear % 4 == 0) ? ((AYear % 100 != 0) ? 29 : ((AYear % 400 == 0) ? 29 : 28)) : 28;
		if (AYear < 1970 || AYear > 2999 || AMonth < 1 || AMonth > 12 || ADate < 1 || ADate > EoMArr[AMonth]) {
			return false;
		}
//	} else {
//		return false;
//	}
	return true;
}

InputValidator.IsDateSelectEmpty = function(AContainerSpan,ACheckAll) {

	var MonthSelect = InputValidator.GetMonthSelect(AContainerSpan);
	var DateSelect = InputValidator.GetDateSelect(AContainerSpan);
	var YearSelect = InputValidator.GetYearSelect(AContainerSpan);
	if (ACheckAll) {
		return (MonthSelect.options[MonthSelect.selectedIndex].value == '' && DateSelect.options[DateSelect.selectedIndex].value == '' && YearSelect.options[YearSelect.selectedIndex].value == '');
	} else {
		return (MonthSelect.options[MonthSelect.selectedIndex].value == '' || DateSelect.options[DateSelect.selectedIndex].value == '' || YearSelect.options[YearSelect.selectedIndex].value == '');
	}

}

InputValidator.GetDateString = function(AContainerSpan) {
	
	var MonthSelect = InputValidator.GetMonthSelect(AContainerSpan);
	var DateSelect = InputValidator.GetDateSelect(AContainerSpan);
	var YearSelect = InputValidator.GetYearSelect(AContainerSpan);
	return (MonthSelect.options[MonthSelect.selectedIndex].value + InputValidator.DateSeparator + DateSelect.options[DateSelect.selectedIndex].value + InputValidator.DateSeparator + YearSelect.options[YearSelect.selectedIndex].value);
	
}

InputValidator.GetMonthSelect = function(AContainerSpan) {
	
	if (typeof AContainerSpan == 'string') {
		AContainerSpan = document.getElementById(AContainerSpan);
	}
	return AContainerSpan.childNodes[0];
	
}

InputValidator.GetDateSelect = function(AContainerSpan) {
	
	if (typeof AContainerSpan == 'string') {
		AContainerSpan = document.getElementById(AContainerSpan);
	}
	return AContainerSpan.childNodes[2];
	
}

InputValidator.GetYearSelect = function(AContainerSpan) {
	
	if (typeof AContainerSpan == 'string') {
		AContainerSpan = document.getElementById(AContainerSpan);
	}
	return AContainerSpan.childNodes[4];
	
}

InputValidator.DoCustomValidation = function(AElement) {
	
	return 'TRUE';
	
}

InputValidator.ValidateField = function(e) {
	
	var i,j;	
	var Element = EventHandler.GetTarget(e);
	var CheckDefArr = InputValidator.CheckDef[Element.id].split(" "); 
	var Message = 'TRUE';
	var CommentDivId = '';
	
	for (i=0; i<CheckDefArr.length; i+=2) {
		if (Message != 'TRUE') break;
		switch (CheckDefArr[i]) {
			case 'required' :
				if (CheckDefArr[i+1].toLowerCase() == 'yes') {
					if (Element.parentNode.id && Element.id.indexOf(Element.parentNode.id) != -1) {
					//this is special for date picker, because a date picker combo box resides inside a span 
					//with id exactly like the combobox but without suffix (see TDateField.php)
					//for example, if this is a due_date_year combobox, then the span id must be due_date
						if (InputValidator.IsDateSelectEmpty(Element.parentNode,true)) {
							Message = 'required field.';
						} else if (InputValidator.IsDateSelectEmpty(Element.parentNode,false)) {
							Message = '';
						}
					} else {
						switch (Element.type) {
							case 'checkbox' :
								if (!Element.checked) {
									Message = 'required field.';
								}
								break;
							case 'select-one' :
								if (Element.options[Element.selectedIndex].value == '') {
									Message = 'required field.';
								}
								break;
							default :
								if (Element.value == '') {
									Message = 'required field.';
								}
						}
					}
				}
				break;
			case 'length' :
				LengthLimits = CheckDefArr[i+1].split("-");
				LengthLimits[0] = parseInt(LengthLimits[0]);
				LengthLimits[1] = parseInt(LengthLimits[1]);
				if (LengthLimits[0] == 0) {
					if (LengthLimits[1] != 0) {
						if (Element.value.length > LengthLimits[1]) {
							Message = 'cannot exceed ' + LengthLimits[1] + ' characters long.';
						}
					}
				} else {
					if (Element.value.length < LengthLimits[0] || Element.value.length > LengthLimits[1]) {
						if (LengthLimits[0] == LengthLimits[1]) {
							Message = 'must exactly be ' + LengthLimits[0] + ' characters long.';
					} else {
							Message = 'must be between ' + LengthLimits[0] + ' and ' + LengthLimits[1] + ' characters long.';
						}
					}
				}
				break;
			case 'type' :
				switch (CheckDefArr[i+1]) {
					case 'general' : 
					  break;
					case 'alphabet_only' :
						Temp = Element.value.toLowerCase();
						for (i=0; i<Temp.length; i++) {
							if (Temp.charAt(i) < 'a' || Temp.charAt(i) > 'z') {
								Message = 'must all consist of alphabets.';
								break;
							}
						}
					  break;
					case 'alphanumeric' : 
						Temp = Element.value.toLowerCase();
						for (i=0; i<Temp.length; i++) {
							if (!(Temp.charAt(i) >= 'a' && Temp.charAt(i) <= 'z') && !(Temp.charAt(i) >= '0' && Temp.charAt(i) <= '9') && Temp.charAt(i) != '_' && Temp.charAt(i) != ' ') {
								Message = 'must all consist of alphanumeric characters.';
								break;
							}
						}
					  break;
					case 'numeric' :
						if (Element.value != '') {
							var RegEx = new RegExp(/(^\d+$)|(^\d+\.\d+$)/);
							if (!Element.value.match(RegEx)) {
								Message = 'must be a number.';
							}
						} 
					  break;
					case 'positive_numeric' :
						if (Element.value != '') {
							var RegEx = new RegExp(/(^\d+$)|(^\d+\.\d+$)/);
							if (!Element.value.match(RegEx) || parseFloat(Element.value) < 0) {
								Message = 'must be a non-negative number (>=0).';
							}
						}
					  break;
					case 'date' : 
						var MonthSelect = InputValidator.GetMonthSelect(Element.parentNode);
						var DateSelect = InputValidator.GetDateSelect(Element.parentNode);
						var YearSelect = InputValidator.GetYearSelect(Element.parentNode);
						if (!InputValidator.IsDateValid(DateSelect.options[DateSelect.selectedIndex].value,MonthSelect.options[MonthSelect.selectedIndex].value,YearSelect.options[YearSelect.selectedIndex].value)) {
							Message = 'not a valid date.';
						}
						break;
					case 'turing' :
						if (document.getElementById(Element.id+'_hidden').value != Element.value) {
							Message = 'Invalid verification code. Please type in the code in its exact cases.';
						}
						break;
				}
				break;
			case 'match' :
				if (document.getElementById(CheckDefArr[i+1]).value != Element.value) {
					Message = 'must equal ' + CheckDefArr[i+1] + '.';
				}
				break;
			case 'range' :
				RangeLimits = CheckDefArr[i+1].split("-");
				RangeLimits[0] = parseInt(RangeLimits[0]);
				RangeLimits[1] = parseInt(RangeLimits[1]);
				Value = parseFloat(Element.value);
				if (isNaN(Value)) {
					Message = 'must be a number.';
				} else {
					if (Value < RangeLimits[0] || Value > RangeLimits[1]) {
						Message = 'must be between ' + RangeLimits[0] + ' and ' + RangeLimits[1];
					}
				}
				break;
			case 'nospace' :
				if (CheckDefArr[i+1].toLowerCase() == 'yes') {
					if (Element.value.indexOf(' ') != -1) {
						Message = 'must not contain any space.';
					}
				}
				break;
		}
	}
	if (InputValidator.CheckDef[Element.id].indexOf('comment_id') == -1) {
		ContainingEl = Element.parentNode.parentNode;
		for (i=0; i<ContainingEl.childNodes.length; i++) {
			if (ContainingEl.childNodes[i].id == Element.id+'_comment') {
				CommentDiv = ContainingEl.childNodes[i];
				break;
			}
		}
		//CommentDivId = Element.id+'_comment';
	} else {
		for (i=0; i<CheckDefArr.length; i+=2) {
			if (CheckDefArr[i] == 'comment_id') {
				CommentDiv = document.getElementById(CheckDefArr[i+1]);
				break;
			}
		}
	}
	
	if (Message == 'TRUE') {
		Message = InputValidator.DoCustomValidation(Element);
	}
	if (Message == 'TRUE') {
		CommentDiv.innerHTML = '<img src="images/correct.gif" width="15" height="15">&nbsp;';
	} else if (Message == '') {
		CommentDiv.innerHTML = '';
	} else {
		CommentDiv.innerHTML = '<img src="images/incorrect.gif" width="15" height="15" align="bottom" title="'+Message+'">&nbsp;';
//		CommentDiv.innerHTML = '<img src="images/incorrect.gif" width="15" height="15" align="bottom">&nbsp;' + Message;
	}
}

InputValidator.AddValidationHandler = function(AControl,AEvent) {

	var j;
	if (AEvent.indexOf('/') != -1) {
		Events = AEvent.split('/');
		for (j=0; j<Events.length; j++) {
			EventHandler.AddEvent(AControl,Events[j],InputValidator.ValidateField);
		}
	} else {
		EventHandler.AddEvent(AControl,AEvent,InputValidator.ValidateField);
	}

}

InputValidator.Initialize = function() {
	
	var Events;
	var i, j;
	
	for (var FieldName in InputValidator.CheckDef) {
		Control = document.getElementById(FieldName);
		if (Control) {
			CheckDefArr = InputValidator.CheckDef[FieldName].split(" ");
			for (i=0; i<CheckDefArr.length; i+=2) {
				if (CheckDefArr[i].toLowerCase() == 'event') {
					if (Control.childNodes.length > 0 && Control.type != 'textarea' && Control.type != 'select-one') {
					//this if is for date/time picker, because all comboboxes are encapsulated inside a span.
					//for example, date picker named due_date will have a span with id of due_date and
					//three comboboxes inside it with id due_date_month, due_date_date, due_date_year
						InputValidator.CheckDef[FieldName] += " comment_id " + FieldName + '_comment';
						var MonthSelect = InputValidator.GetMonthSelect(Control);
						var DateSelect = InputValidator.GetDateSelect(Control);
						var YearSelect = InputValidator.GetYearSelect(Control);
						InputValidator.AddValidationHandler(MonthSelect,CheckDefArr[i+1]);
						InputValidator.CheckDef[MonthSelect.id] = InputValidator.CheckDef[FieldName]; 
						InputValidator.AddValidationHandler(DateSelect,CheckDefArr[i+1]);
						InputValidator.CheckDef[DateSelect.id] = InputValidator.CheckDef[FieldName]; 
						InputValidator.AddValidationHandler(YearSelect,CheckDefArr[i+1]);
						InputValidator.CheckDef[YearSelect.id] = InputValidator.CheckDef[FieldName]; 
					} else {
						InputValidator.AddValidationHandler(Control,CheckDefArr[i+1]);
					}
				}
			}
		}
	}
	
}


