/** Class for displaying a handy calendar for Date type fields.
	(revised, original version: Julian Robichaux -- http://www.nsftools.com) */
var DatePicker = {

	// Container Div id
	divId: 'datePicker',
	// Container IFrame id
	iframeId: 'datePickerFrame',
	// Day and month names
	dayArrayShort: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
	dayArrayLong: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
	monthArrayShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
	monthArrayLong: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
	// Date format and separator, e.g. yy-mm-dd
	format: 'ymd',
	separator: '-',

	/**
	 * Set the position, the format and draw the datepicker beneath an element.
	 *
	 * @param dateFieldId         Id of the date input element.
	 * @param belowThisObjectId   Id of the element which indicates where to put the datepicker.
	 *                            Default: under the date input element
	 * @param dtFormat            Format of the date. If null, the default value is used.
	 * @param dtSep               Separator of the date. If null, the default value is used.
	 */
	show: function(dateFieldId, belowThisObjectId, dtFormat, dtSep) {
		var targetDateField = document.getElementById(dateFieldId);
		DatePicker.separator = (dtSep ? dtSep : DatePicker.separator);
		DatePicker.format = (dtFormat ? dtFormat : DatePicker.format);

		if (!belowThisObjectId) {
	    	belowThisObjectId = dateFieldId;
		}
		var belowThisObject = document.getElementById(belowThisObjectId);
		var x = belowThisObject.offsetLeft;
		var y = belowThisObject.offsetTop + belowThisObject.offsetHeight ;
		var parent = belowThisObject;
		while (parent.offsetParent) {
			parent = parent.offsetParent;
			x += parent.offsetLeft;
			y += parent.offsetTop;
		}
	  	DatePicker.draw(targetDateField, x, y);
	},

	/**
	 * Display the datepicker.
	 *
	 * @param targetDateField   Object of the input field to be attached.
	 * @param x                 Left position of the datepicker in pixels.
	 * @param y                 Top position of the datepicker in pixels.
	 */
	draw: function(targetDateField, x, y) {
		var dt = DatePicker.getFieldDate(targetDateField.value);
	
		if (!document.getElementById(DatePicker.divId)) {
			var newNode = document.createElement('div');
			newNode.setAttribute('id', DatePicker.divId);
			newNode.setAttribute('class', 'dpDiv');
			newNode.setAttribute('style', 'visibility: hidden;');
			document.body.appendChild(newNode);
		}

		var pickerDiv = document.getElementById(DatePicker.divId);
		pickerDiv.style.position = 'absolute';
		pickerDiv.style.left = x + 'px';
		pickerDiv.style.top = y + 'px';
		pickerDiv.style.visibility = (pickerDiv.style.visibility == 'visible' ? 'hidden' : 'visible');
		pickerDiv.style.display = (pickerDiv.style.display == 'block' ? 'none' : 'block');
		pickerDiv.style.zIndex = 10000;

		DatePicker.refresh(targetDateField.id, dt.getFullYear(), dt.getMonth(), dt.getDate());
	},

	/**
	 * Refresh the calendar.
	 *
	 * @param dateFieldId   Id of the date input element.
	 * @param year          Current year value.
	 * @param month         Current month value.
	 * @param day           Current day value.
	 */
	refresh: function(dateFieldId, year, month, day) {
		var thisDay = new Date();

		if (month >= 0 && year > 0) {
			thisDay = new Date(year, month, 1);
		} else {
			day = thisDay.getDate();
			thisDay.setDate(1);
		}

		var html = '<table cols="7" class="dpTable">';
		html += '<tr class="dpTitleTR">';
		html += '<td class="dpButtonTD">' + DatePicker.getButtonHtml(dateFieldId, thisDay, -1, "&lt;") + '</td>';
		html += '<td colspan="5" class="dpTitleTD"><div class="dpTitleText">' + DatePicker.monthArrayLong[ thisDay.getMonth()] + " " + thisDay.getFullYear() + '</div></td>';
		html += '<td class="dpButtonTD">' + DatePicker.getButtonHtml(dateFieldId, thisDay, 1, "&gt;") + '</td>';
		html += '</tr>';
		html += '<tr class="dpDayTR">';
		for (i = 0; i < DatePicker.dayArrayShort.length; i++) {
			html += '<td class="dpDayTD">' + DatePicker.dayArrayShort[i] + '</td>';
		}
		html += '</tr>';
		html += '<tr class="dpTR">';
		for (i = 0; i < thisDay.getDay(); i++) {
	    	html += '<td class="dpTD" onMouseOut="this.className=\'dpTD\';" onMouseOver="this.className=\'dpTDHover\';">&nbsp;</td>';
		}
		do {
			dayNum = thisDay.getDate();
			if (dayNum == day) {
				html += '<td class="dpDayHighlightTD" onMouseOut="this.className=\'dpDayHighlightTD\';" onMouseOver="this.className=\'dpTDHover\';" ';
				html += ' onclick=\"DatePicker.updateField(\'' + dateFieldId + '\', \'' + DatePicker.getDateString(thisDay) + '\');">';
				html += '<div class="dpDayHighlight">' + dayNum + '</div></td>';
			} else {
				html += '<td class="dpTD" onMouseOut="this.className=\'dpTD\';" onMouseOver="this.className=\'dpTDHover\';" ';
				html += ' onclick="DatePicker.updateField(\'' + dateFieldId + '\', \'' + DatePicker.getDateString(thisDay) + '\');">' + dayNum + '</td>';
			}

			if (thisDay.getDay() == 6) {
				html += '</tr><tr class="dpTR">';
			}

			thisDay.setDate(thisDay.getDate() + 1);
		} while (thisDay.getDate() > 1)
		if (thisDay.getDay() > 0) {
			for (i = 6; i > thisDay.getDay(); i--) {
				html += '<td class="dpTD" onMouseOut="this.className=\'dpTD\';" onMouseOver="this.className=\'dpTDHover\';">&nbsp;</td>';
			}
		}
		html += '</tr>';
		var today = new Date();
		var todayString = 'Today is ' + DatePicker.dayArrayLong[today.getDay()] + ', ' + DatePicker.monthArrayShort[ today.getMonth()] + ' ' + today.getDate();
		html += '<tr class="dpTodayButtonTR"><td colspan="7" class="dpTodayButtonTD">';
		html += '<button class="dpTodayButton" onClick="DatePicker.refresh(\'' + dateFieldId + '\');">this month</button>';
		html += '<button class="dpTodayButton" onClick="DatePicker.updateField(\'' + dateFieldId + '\');">close</button>';
		html += '</td></tr></table>';

		document.getElementById(DatePicker.divId).innerHTML = html;
		DatePicker.adjustIFrame();
	},

	/**
	 * Return the html of the buttons that navigate us to previous and next months.
	 *
	 * @param dateFieldId   Date input element id.
	 * @param dateVal       The current date.
	 * @param adjust        Month to be added to the current date when the button is clicked: 1 or -1.
	 * @param label         Button label.
	 * @return string html.
	 */
	getButtonHtml: function(dateFieldId, dateVal, adjust, label) {
		var newMonth = (dateVal.getMonth () + adjust) % 12;
		var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
		if (newMonth < 0) {
			newMonth += 12;
			newYear += -1;
		}
		return '<button class="dpButton" onClick="DatePicker.refresh(\'' + dateFieldId + '\', ' + newYear + ', ' + newMonth + ');">' + label + '</button>';
	},

	/**
	 * Convert date value to well-formatted string.
	 *
	 * @param dateVal   The date.
	 * @return string.
	 */
	getDateString: function(dateVal) {
		var dayString = '00' + dateVal.getDate();
		var monthString = '00' + (dateVal.getMonth()+1);
		dayString = dayString.substring(dayString.length - 2);
		monthString = monthString.substring(monthString.length - 2);

		switch (DatePicker.format) {
	 		case 'dmy':
				return dayString + DatePicker.separator + monthString + DatePicker.separator + dateVal.getFullYear();
			case 'ymd':
				return dateVal.getFullYear() + DatePicker.separator + monthString + DatePicker.separator + dayString;
			case 'mdy':
			default :
				return monthString + DatePicker.separator + dayString + DatePicker.separator + dateVal.getFullYear();
		}
	},

	/**
	 * Convert a well-formatted string to date.
	 *
	 * @param dateString   The date string.
	 * @return Date object.
	 */
	getFieldDate: function(dateString) {
		var dateVal;
		var dArray;
		var d, m, y;

		try {
			dArray = DatePicker.splitDateString(dateString);
			if (dArray) {
				switch (DatePicker.format) {
					case 'dmy':
						d = parseInt(dArray[0], 10);
						m = parseInt(dArray[1], 10) - 1;
						y = parseInt(dArray[2], 10);
						break;
					case 'ymd':
						d = parseInt(dArray[2], 10);
						m = parseInt(dArray[1], 10) - 1;
						y = parseInt(dArray[0], 10);
						break;
					case 'mdy':
					default :
						d = parseInt(dArray[1], 10);
						m = parseInt(dArray[0], 10) - 1;
						y = parseInt(dArray[2], 10);
						break;
				}
				dateVal = new Date(y, m, d);
			} else if (dateString) {
				dateVal = new Date(dateString);
			} else {
				dateVal = new Date();
			}
		} catch(e) {
			dateVal = new Date();
		}
		return dateVal;
	},

	/**
	 * Split the date by the separator.
	 *
	 * @param dateString   The string formatted date.
	 * @return array or false if separator is not found.
	 */
	splitDateString: function(dateString) {
		if (dateString.indexOf(DatePicker.separator) >= 0) {
			return dateString.split(DatePicker.separator);
		}
		return false;
	},

	/**
	 * Update the date input field value and close the datepicker.
	 *
	 * @param dateFieldId   Id of the input element that contains the date.
	 * @param dateString    String value of the new date.
	 */
	updateField: function(dateFieldId, dateString) {
		var targetDateField = document.getElementById(dateFieldId);
		if (dateString) {
			targetDateField.value = dateString;
		}
		DatePicker.hide();
		targetDateField.focus();
	},

	/**
	 * Hide the datepicker.
	 */
	hide: function() {
		var pickerDiv = document.getElementById(DatePicker.divId);
		if (pickerDiv != null) {
			pickerDiv.style.visibility = 'hidden';
			pickerDiv.style.display = 'none';
			DatePicker.adjustIFrame();
		}
	},
	
	/**
	 * Display an iframe for a picker element to eliminate z-index problems with applets and list elements.
	 *
	 * @param pickerDiv   Id of the picker element. If null, the default value is used.
	 * @param iFrameDiv   If of the iframe element. If null, the default value is used.
	 */
	adjustIFrame: function(pickerDiv, iFrameDiv) {
		if (navigator.userAgent.toLowerCase().indexOf('opera') != -1) {
			return;
		}
		try {
			if (!document.getElementById(DatePicker.iframeId)) {
				var newNode = document.createElement('iframe');
				newNode.setAttribute('id', DatePicker.iframeId);
				newNode.setAttribute('src', "");
				newNode.setAttribute('scrolling', 'no');
				newNode.setAttribute ('frameborder', '0');
				document.body.appendChild(newNode);
			}
	
			if (!pickerDiv) {
				pickerDiv = document.getElementById(DatePicker.divId);
			}
			if (!iFrameDiv) {
				iFrameDiv = document.getElementById(DatePicker.iframeId);
			}
			try {
				iFrameDiv.style.position = 'absolute';
				iFrameDiv.style.width = pickerDiv.offsetWidth;
				iFrameDiv.style.height = pickerDiv.offsetHeight ;
				iFrameDiv.style.top = pickerDiv.style.top;
				iFrameDiv.style.left = pickerDiv.style.left;
				iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1;
				iFrameDiv.style.visibility = pickerDiv.style.visibility ;
				iFrameDiv.style.display = pickerDiv.style.display;
			} catch(e) {}
		} catch (ee) {}
	}
};
