/**
 * 
 * DESCRIPTION:
 * This file contains the functionality of a PopUp Calendar to enable simple specification of dates.
 *
 * USE:
 * A calendar is bound to an input text field and opened by clicking on a link "javascript:ShowCalendar(textfield,withtime)".
 * "textfield" has to contain a reference to the textfield the calendar is used with, and "withtime" is a boolean value indicating
 * if the calendar should be extended by a time display.
 *
 * PARAMETERS:
 * The calendar can be customized by setting some formatting parameters:
 * - month_names: Array containing the month names to display in a SELECT box
 * - weekday_prefs: Prefixes of the weekdays to display in the table header of the calendar
 * - min_year: start year of the calendar
 * - max_year: end year of the calendar
 * - date_sep: Separator for the date ("." or "/" or ...)
 * - month_pos: Position of the month in the date
 * - day_pos: Position of the day in the date
 * - full_year: Indicates if the year should be parsed and formatted as a 4-digit-value
 *
 * - calendar_src: Relative path of this file (as it is included by the dynamically created PopUp calendar)
 *
 * STYLE:
 * The style of the calendar can be set in a css file whose location has to be set in "css_src". 
 * 
 * AUTHOR:
 * Amin Fischer
 */

// Define the month names
var month_names = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");

// Define weekday prefixes
var weekday_prefs = new Array("Mo","Tu","We","Th","Fr","Sa","Su");

// Set minimum and maximum year
var min_year = 1940;
var max_year = 2050;

// The following information is import for the parsing of dates
var date_sep = ".";
var month_pos = 1;
var day_pos = 0;
var full_year = true;

// Style file
//var css_src = "layout/calendar.css";

// Relative path of the calendar
var calendar_src = "javascript/calendar.js";

/**
 * 
 * This function opens a new calendar window and writes the HTML code for it.
 *
 */
function ShowCalendar(element_id,withtime) {
	var element = document.getElementById(element_id);

	// Close old calendar window if it already exists
	if (window['calendar_win'] != undefined)
		window['calendar_win'].close();
		
	// Open a new calendar window
	var calendar_win = window.open("lib/calendar.html?element="+element.id+"&withtime="+(withtime?"true":"false"),"calendar_win","dependent=yes,status=no,location=no,scrollbars=no,toolbar=no,hotkeys=no,width=240,height="+(withtime?230:205));
}

/**
 *
 * Writes the HMTL code for the calendar window.
 *
 **/
function Initialize() {
	// Get paramters from url
	var params = window.location.search.split("&");
	
	// Get date from element
	element = params[0].substring(9);
	date = parseDate(opener.document.getElementById(element).value);
	
	if (!date)
		date = new Date();
		
	date = new Date(date.getFullYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds());
		
	// Withtime?
	withtime = (params[1].substring(9) == "true");
	if (withtime) {
		document.getElementById("time").className = "";		
		document.forms[0].minute.value = formatNumber(date.getMinutes(),2);
		document.forms[0].second.value = formatNumber(date.getSeconds(),2);
		document.forms[0].hour.value = formatNumber(date.getHours(),2);
	}
	
	// Write months
	var month_elem = document.forms[0].month;
	for (var i=0;i<12;i++) {
		var option = new Option(month_names[i],i,false,(i == date.getMonth()));
		month_elem.options[i] = option;
	}
	
	// Write years
	var year_elem = document.forms[0].year;
	for (var i=min_year;i<=max_year;i++) {
		var option = new Option(i,i,false,(i == date.getFullYear()));
		year_elem.options[i-min_year] = option;
	}

	WriteCalendar();
}

/**
 * 
 * This function parses a given date string and returns false or a given date.
 *
 */
function parseDate(date) {
	// Check if time occurs in field
	var field = date.split(" ");
	var dateArray;
	if (field == undefined)
		dateArray = date.split(date_sep);
	else if (field.length !=2)
		dateArray = date.split(date_sep);
	else {
		dateArray = field[0].split(date_sep);
		var timeArray = field[1].split(":");
	}
	
	if (dateArray == undefined)
		return false;
	else if (dateArray && dateArray.length != 3)
		return false;
	else {
		// Get year
		var year = getInt(dateArray[2]);
		if (year < 40)
			year += 2000;
		
		// Get month
		var month = getInt(dateArray[month_pos])-1;
		if (month < 0 || month > 11)
			return false;
		
		// Get day
		var day = getInt(dateArray[day_pos]);
		if (day < 1 || day > daysInMonth(month,year))
			return false;
		
		// Return date or datetime object
		if (timeArray != undefined && timeArray.length == 3 && timeArray[0] < 24 && timeArray[1] < 60 && timeArray[2] < 60)
			return new Date(year,month,day,timeArray[0],timeArray[1],timeArray[2]);
		else
			return new Date(year,month,day,0,0,0);
	}
}

/**
 * 
 * Formats a given date and returns a string.
 *
 */
function formatDate(date) {
	var returnDate = "";
	if (day_pos == 0) {
		returnDate += formatNumber(date.getDate(),2)+date_sep;
		returnDate += formatNumber(date.getMonth()+1,2)+date_sep;
	}
	else {
		returnDate += formatNumber(date.getMonth()+1,2)+date_sep;
		returnDate += formatNumber(date.getDate(),2)+date_sep;
	}
	
	if (full_year)
		returnDate += formatNumber(date.getFullYear(),4);
	else
		returnDate += formatNumber(date.getYear(),2);
	
	if (withtime)
		returnDate += " "+formatNumber(document.forms[0].hour.value,2)+":"+formatNumber(document.forms[0].minute.value,2)+":"+formatNumber(document.forms[0].second.value,2);
	
	return returnDate;
}

/**
 * 
 * Formats a number with leading zeros.
 *
 */
function formatNumber(num,zeros) {
	var s = String(num);
	for (var i = zeros-s.length;i>0;i--)
		s = "0" + s;
	if (zeros < s.length)
		s = s.substr(s.length-zeros,zeros);
	return s;
}

/**
 * 
 * This function write the calendar for the current date into the appropriate div container.
 *
 */
function WriteCalendar() {
	// Compose HTML code
	var h = "<table class=\"calendar\"><tr>";
	
	// Write weekday prefixes as headers
	for (var i=0;i<7;i++)
		h += "<th>"+weekday_prefs[i]+"</th>";
	h += "</tr>";
	
	var startDay = new Date(date.getFullYear(),date.getMonth(),1);
	var emptyCells;
	if (startDay.getDay() == 0)
		emptyCells = 6;
	else
		emptyCells = startDay.getDay()-1;
	
	// Print empty table cells
	for (i=0;i<emptyCells;i++)
		h += "<td></td>";
	
	for (var j=emptyCells+1;j<=34;j++) {
		if (j % 7 == 1)
			h += "<tr>";
		
		// Background color for table cell
		if (j-emptyCells == date.getDate())
			h += "<td class=\"a\">";
		else if (j % 7 == 6 || j % 7 == 0)
			h += "<td class=\"h\">";
		else
			h += "<td>";
		
		if (j-emptyCells <= daysInMonth(date.getMonth(),date.getFullYear()))
			h += "<a href=\"javascript:returnDate("+(j-emptyCells)+");\">"+(j-emptyCells)+"</a>";
		
		h += "</td>";
		
		if (j % 7 == 0)
			h += "</tr>";
	}
	h += "</table>";
	document.getElementById("calendar").innerHTML = h;
}

/**
 * 
 * Changes the dates and rewrites the calendar.
 *
 */
function change() {
	var newYear = document.getElementById("year").value;
	var newMonth = document.getElementById("month").value;
	var newDay = Math.min(daysInMonth(newMonth,newYear),date.getDate());
	date = new Date(newYear,newMonth,newDay);
	WriteCalendar();
}

/**
 * 
 * Returns the (formatted) date to the main window.
 *
 */
function returnDate(day) {
	var dateString = formatDate(new Date(date.getFullYear(),date.getMonth(),day,0,0,0));
	
	// Set date in the given element
	opener.document.getElementById(element).value = dateString;
	
	// Close windows
	window.close();
	return true;
}

/**
 * 
 * Returns the integer value of a string. If the string is not parseable, -1 is returned
 *
 */
function getInt(s) {
	if (isNaN(parseInt(s)))
		return -1;
	else 
		return parseInt(s);	
}

/**
 * 
 * Returns if year is leap year.
 *
 */
function isLeapYear(year) {
	return (year % 4 == 0 && year % 100 != 0);
}

/**
 * 
 * Returns number of days in a month.
 *
 */
function daysInMonth(month,year) {
	if (month == 1 && isLeapYear(year))	
		return 29;
	else if (month == 1)
		return 28;
	else if (month == 3 || month == 5 || month == 8 || month == 10)
		return 30;
	else
		return 31;
}
