










var formatDate = buildFormat("M/d/yyyy");
var formatTime = buildFormat("h:mm tt");
var parseDate = buildDateParser("M/d/yyyy");


var formatHour   = buildFormat("h:mm tt".replace(/[^hH]/g,""));
var formatMinute = buildFormat("h:mm tt".replace(/[^m]/g,""));










function getMonthName(m) {
	var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
	return months[m-1];
}










function getMonthAbbr(m) {
	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
	return months[m-1];
}










function getDayName(d) {
	var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
	return days[d];
}










function getDayAbbr(d) {
	var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
	return days[d];
}










function getDayLetter(d) {
	var days = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
	return days[d];
}








function getFirstDayOfWeek() {
	return 0;
}










function getHour12(h) {
	if(h%12 == 0) {
		return 12;
	} else {
		return h%12;
	}
}










function getAMPM(h)
{
	var ampm = ['AM', 'PM'];
	return (h < 12) ? ampm[0]:ampm[1];
}










function getAMPMAbbr(h) {
	var ampm = ['A','P'];
	return (h < 12) ? ampm[0]:ampm[1];
}












function buildFormat(dateFormat) {
	
	dateFormat = dateFormat.replace(/(.)(?!\1)/g,"$1\n");
	var datePieces = dateFormat.split(/\n/);
	var formatter;

	for(var i=0; i<datePieces.length; i++) {
		if(datePieces[i].match(/^y+$/)) { 
			switch(datePieces[i].length) {
			case 2:
				datePieces[i] = "((date.getFullYear() % 100).toString())";
				break;
			case 4:
				datePieces[i] = "(date.getFullYear().toString())";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^M+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "((date.getMonth()+1).toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(date.getMonth()+1,2))";
				break;
			case 3:
				datePieces[i] = "(getMonthAbbr(date.getMonth()+1))";
				break;
			case 4:
				datePieces[i] = "(getMonthName(date.getMonth()+1))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^d+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(date.getDate().toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(date.getDate(),2))";
				break;
			case 3:
				datePieces[i] = "(getDayAbbr(date.getDay()))";
				break;
			case 4:
				datePieces[i] = "(getDayName(date.getDay()))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^h+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(getHour12(date.getHours()).toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(getHour12(date.getHours()),2))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^H+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(date.getHours().toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(date.getHours(),2))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^m+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(date.getMinutes().toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(date.getMinutes(),2))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^s+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(date.getSeconds().toString())";
				break;
			case 2:
				datePieces[i] = "(padNumber(date.getSeconds(),2))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else if(datePieces[i].match(/^t+$/)) { 
			switch(datePieces[i].length) {
			case 1:
				datePieces[i] = "(getAMPMAbbr(date.getHours()))";
				break;
			case 2:
				datePieces[i] = "(getAMPM(date.getHours()))";
				break;
			default:
				datePieces[i] = "''";
			}
		} else {
			datePieces[i] = "('"+datePieces[i]+"')";
		}
	}

	eval("formatter = function(date) { if(date == null) return \"\"; else return " + datePieces.join("+") + "; }");
	return formatter;
}












function buildDateParser(dateFormat) {
	var regex;

	dateFormat = dateFormat.replace(/[^yMd]*([yMd])+[^yMd]*/g,"$1");
	switch(dateFormat.indexOf('y')) { 
	case 0: 
		regex = /^\s*(?:(?:((?:\d{2})?\d{2})\D)?(\d{1,2})\D(\d{1,2})|(?:((?:\d{2})?\d{2}))?(\d{2})(\d{2}))\s*$/;
		break;
	case 1: 
		regex = /^\s*(?:(\d{1,2})\D(?:((?:\d{2})?\d{2})\D)?(\d{1,2})|(\d{2})(?:((?:\d{2})?\d{2}))?(\d{2}))\s*$/;
		break;
	case 2: 
		regex = /^\s*(?:(\d{1,2})\D(\d{1,2})(?:\D((?:\d{2})?\d{2}))?|(\d{2})(\d{2})(?:((?:\d{2})?\d{2}))?)\s*$/;
		break;
	}

	return function(regex,dateFormat) { 
		return function(dateString) {
			var parsed, year, month, day;
			var matches = dateString.match(regex);
			if(matches == null) {
				dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nPlease reenter the date in @MYCHART@DATEFORMAT@ format.",dateString);
				return;
			}

			if(matches[1] != null && matches[1] != "") {   
				year   = matches[(dateFormat.indexOf('y')+1)];
				month  = matches[(dateFormat.indexOf('M')+1)];
				day    = matches[(dateFormat.indexOf('d')+1)];
			} else {                                       
				year   = matches[(dateFormat.indexOf('y')+4)];
				month  = matches[(dateFormat.indexOf('M')+4)];
				day    = matches[(dateFormat.indexOf('d')+4)];
			}

			parsed = makeDate(year,month,day);
			if(month < 1 || month > 12) {
				dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe month must be between 1 and 12.",dateString);
			} else if(parsed.getDate() != day) {
				dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe day is not valid for this month.",dateString);
			} else {
	            		return parsed;
	            	}
		}
	}(regex,dateFormat);
}













function makeDate(year,month,day) {
	return makeInstant(year,month,day,0,0,0);
}













function makeTime(hour,minute,second) {
	return makeInstant(null,null,null,hour,minute,second);
}
















function makeInstant(year,month,day,hour,minute,second) {
	var now = new Date();
	
	
	if(year == null) {
		year = now.getFullYear();
	} else {
		year = Number(year);
		if(year < 30)
			year+=2000;
	}
	
	if(month == null) {
		month  = now.getMonth()+1;
		if(day == null) {
			day = now.getDate();
		}
	}
	else if(day == null) {
		day = 1; 
	}
	
	if(hour   == null) hour   = now.getHours();
	if(minute == null) minute = now.getMinutes();
	if(second == null) second = now.getSeconds();
	
	return new Date(year,Number(month)-1,day,hour,minute,second);
}




















function formatDateField(field,validType,min,max) {
	if(field.value.match(/^\s*$/)) {
		return true;
	}

	var date = parseDate(field.value);
	var dateString;
	var today = new Date();
	today.setHours(0); today.setMinutes(0); today.setSeconds(0); today.setMilliseconds(0); 

	if(date == null) { 
		return false;
	} else {
		dateString = formatDate(date);
	}

	switch(validType) {
	case 1: 
		if(date >= today) {
			dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe date must be in the past.",dateString);
			return false;
		}
		break;
	case 2: 
		if(date <= today) {
			dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe date must be in the future.",dateString);
			return false;
		}
		break;
	case 3: 
		if(date < today) {
			dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe date must be today or in the future.",dateString);
			return false;
		}
		break;
	case 4: 
		if(date > today) {
			dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe date must be today or in the past.",dateString);
			return false;
		}
		break;
	case 5: 
		if(date < min || date > max) {
			dateInputError("@MYCHART@ENTEREDDATE@ is not valid.\nThe date must be between @MYCHART@MINDATE@ and @MYCHART@MAXDATE@.",dateString,min,max);
			return false;
		}
		break;
	default:
		return false;
	}

	field.value = dateString;
	return true;
}














function dateInputError(str,dateString,min,max) {
	alert(str.replace(/@MYCHART@DATEFORMAT@/ ,"M/d/yyyy").
	          replace(/@MYCHART@ENTEREDDATE@/,dateString).
	          replace(/@MYCHART@MINDATE@/    ,formatDate(min)).
	          replace(/@MYCHART@MAXDATE@/    ,formatDate(max)));
}
