
// Wrapper function used as a private namespace
function dateSelector() {


// General functions to set events
function setEventById(id, evt, func) {
	var obj = document.getElementById(id);
	if (obj) {
		setEventByObject(obj, evt, func);
	}
}

function setEventByObject(obj, evt, func) {
	if (obj.addEventListener) {
		obj.addEventListener(evt, func, false);
	}
	else if (obj.attachEvent) {
		obj.attachEvent('on' + evt, func);
	}
}


var imagePath = '../../images/';
var millisPerMinute = 60 * 1000;
var millisPerHour   = millisPerMinute * 60;
var millisPerDay    = millisPerHour * 24;
var dateSelectorObj;
var currentElement;
var currentDate;
var today;
var currentYear;
var currentMonth;
var currentDay;
var currentHour;
var currentMinute;
var currentSecond;
var selectedYear;
var selectedMonth;
var selectedDay;
var selectedHour;
var selectedMinute;
var selectedSecond;
var selectorVisible = false;
var showTimeSelector = false;
var defaultYear = 1980;
var defaultMonth = 0;
var defaultDay = 1;



function insertAdjacentHTML(obj, where, htmlStr) {

	if (obj.insertAdjacentHTML) {
	obj.insertAdjacentHTML(where, htmlStr);
	return;
	}

	var r = obj.ownerDocument.createRange();
	r.setStartBefore(obj);
	var parsedNode = r.createContextualFragment(htmlStr);

	switch (where){
	case 'beforeEnd':
		obj.appendChild(parsedNode);
		break;
	case 'afterEnd':
		obj.parentNode.insertBefore(parsedNode, obj.nextSibling);
	break;
	}

}


this.show = function showDateSelector(formName, fieldName, showTime) {

	if (selectorVisible) {
		return;
	}
	else {
		selectorVisible = true;
	}

	showTimeSelector = showTime;

	if (!dateSelectorObj) {
		today = new Date();
		today.setFullYear(defaultYear, defaultMonth, defaultDay);
		writeSelectorHTML();
		dateSelectorObj = document.getElementById("dateSelector");
	}

	currentElement = document.forms[formName].elements[fieldName];

	if (currentElement.value) {
		currentDate  = new Date(parseInt(currentElement.value));
		selectedYear  = currentDate.getUTCFullYear();
		selectedMonth = currentDate.getUTCMonth();
		selectedDay   = currentDate.getUTCDate();
		selectedHour  = currentDate.getUTCHours();
		selectedMinute = currentDate.getUTCMinutes();
		selectedSecond = currentDate.getUTCSeconds();
	} else {
		currentDate  = new Date(today);
	}

	currentYear  = currentDate.getUTCFullYear();
	currentMonth = currentDate.getUTCMonth();
	currentDay   = currentDate.getUTCDate();
	currentHour  = currentDate.getUTCHours();
	currentMinute = currentDate.getUTCMinutes();
	currentSecond = currentDate.getUTCSeconds();
	currentDate.setUTCHours(0, 0, 0, 0);

	createCalendarArea();

	var clickedObj = document.getElementById('dateSelectorTable_'+ fieldName);

	dateSelectorObj.style.top  = getTop(clickedObj) + 'px';
	dateSelectorObj.style.left = getLeft(clickedObj) + clickedObj.offsetWidth + 'px';
	dateSelectorObj.style.visibility = "visible";
};


function hideDateSelector(evt) {

	if (!evt) { evt = window.event; }

	if (!selectorVisible) { return; }

	if (dateSelectorObj) {
		if (evt && evt.target) {
			var tableId = "dateSelectorTable_" + currentElement.name;
			var rel = evt.target;

			while (rel) {
				if ((rel.id == "dateSelector") || (rel.id == tableId)) {
					return;
				} else {
					rel = rel.parentNode;
				}
			}

		} else if (evt) {
			var clickX = evt.clientX + document.body.scrollLeft + document.documentElement['scrollLeft'];
			var clickY = evt.clientY + document.body.scrollTop  + document.documentElement['scrollTop'];

			if (clickX > getLeft(dateSelectorObj) &&
				clickX < getLeft(dateSelectorObj) + dateSelectorObj.offsetWidth &&
				clickY > getTop(dateSelectorObj) &&
				clickY < getTop(dateSelectorObj) + dateSelectorObj.offsetHeight) {
				return;
			}

			var dateSelectorTable = document.getElementById('dateSelectorTable_'+ currentElement.name);

			if (clickX > getLeft(dateSelectorTable) &&
				clickX < getLeft(dateSelectorTable) + dateSelectorTable.offsetWidth &&
				clickY > getTop(dateSelectorTable) &&
				clickY < getTop(dateSelectorTable) + dateSelectorTable.offsetHeight) {
				return;
			}
		}
		dateSelectorObj.style.visibility = "hidden";
		selectorVisible = false;
	}
}



function createCalendarArea() {

	var dayNames = new Array("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
	var monthNames = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

	var firstOfMonth = new Date(currentYear, currentMonth, 1);

	var offsetDays;
	switch (firstOfMonth.getDay()) {
		case 0:
			offsetDays = 6;
			break;
		case 1:
			offsetDays = 7;
			break;
		default:
			offsetDays = firstOfMonth.getDay()-1;
	}

	var calendarStart = new Date(firstOfMonth.getTime() - (millisPerDay * offsetDays));
	calendarStart.setHours(12);

	var calendar = '<table class="calendar">';
	calendar += "<tr>";

	for(var i = 0; i < dayNames.length; i++) {
		calendar += "<th>" + dayNames[i] + "</th>";
	}

	calendar += "</tr>";

	for(var j = 0; j <= 41;	j++) {
		if ((j % 7) === 0) {
			calendar += "<tr>";
		}
		var styleClass = "";
		var day = new Date(calendarStart.getTime() + (millisPerDay * j));
		day.setUTCHours(0, 0, 0, 0);

		if (day.getUTCFullYear() == today.getUTCFullYear()  &&
			day.getUTCMonth()    == today.getUTCMonth() &&
			day.getUTCDate()     == today.getUTCDate()) {
			styleClass += "today ";
		}

		if (day.getUTCFullYear() == selectedYear  &&
			day.getUTCMonth()    == selectedMonth &&
			day.getUTCDate()     == selectedDay) {
			styleClass += "selected ";
		}

		if (day.getMonth() != currentMonth) {
			styleClass += "notInMonth ";
		} else {
			styleClass += "inMonth ";
		}

		if (j % 7 == 6) {
			styleClass += "redLetterDay";
		}

		calendar += "<td><a href='javascript: dateSelector.set(\"" + day.getTime() + "\")' class='" + styleClass + "'>" + day.getDate() + "</a></td>";

		if (j%7 == 6) {
			calendar += "</tr>";
		}

	}

	calendar += "</table>";

	var monthOptions = "";
	var selected = "";

	for(var k = 0; k <= 11; k++ ) {
		if (k == currentMonth) {
			selected = ' selected="selected"';
		} else {
			selected = "";
		}

		monthOptions += '<option' + selected + '>' + monthNames[k] + '</option>';
	}

	var hourOptions = "";

	for(var l = 0; l <= 23; l++ ) {
		if (l == currentHour) {
			selected = ' selected="selected"';
		} else {
			selected = "";
		}

		hourOptions += '<option' + selected + '>' + (l<10 ? '0':'') + l + '</option>';
	}

	var minuteOptions = "";

	for(var m = 0; m <= 59; m++ ) {
		if (m == currentMinute) {
			selected = ' selected="selected"';
		} else {
			selected = "";
		}

		minuteOptions += '<option' + selected + '>' + (m<10 ? '0':'') + m + '</option>';
	}

	calendar =
		'<table>' +
		'<tr>' +
		'<td class="buttons"><input type="button" class="button" value="&lt;" onclick = "dateSelector.advanceMonth(-1)"/>' +
		'<select name="currentMonth" class="monthRolldown" onchange="dateSelector.changeMonth(this.selectedIndex)">' + monthOptions + '</select>' +
		'<input type="button" class="button" value="&gt;" onclick = "dateSelector.advanceMonth(1)"/>&nbsp;' +
		'<input type="button" class="button" value="&lt;" onmousedown="if (typeof yearIntervalId == \'undefined\' || yearIntervalId == 0) {yearIntervalId = setInterval(\'dateSelector.advanceMonth(-12)\', 160);}" onmouseup="clearInterval(yearIntervalId); yearIntervalId=0;" onmouseout="clearInterval(yearIntervalId); yearIntervalId=0;" onclick="dateSelector.advanceMonth(-12)"/>' +
		'<input type="text"   class="year"   name="currentYear" value="' + currentYear + '" onfocus="blur();">' +
		'<input type="button" class="button" value="&gt;" onmousedown="if (typeof yearIntervalId == \'undefined\' || yearIntervalId == 0) {yearIntervalId = setInterval(\'dateSelector.advanceMonth(12)\', 160);}" onmouseup="clearInterval(yearIntervalId); yearIntervalId=0;" onmouseout="clearInterval(yearIntervalId); yearIntervalId=0;" onclick="dateSelector.advanceMonth(12)"/></td>' +
		'</tr>' +
		'<tr>' +
		'<td align="center">' + calendar + '</td>' +
		'</tr>' +

		(showTimeSelector ? (
		'<tr>' +
		'<td class="buttons"><input type="button" class="button" value="&lt;" onclick = "dateSelector.advanceHour(-1)"/>' +
		'<select name="currentHour" class="timeRolldown" onchange="dateSelector.changeHour(this.options[this.selectedIndex].value)">' + hourOptions + '</select>' +
		'<input type="button" class="button" value="&gt;" onclick = "dateSelector.advanceHour(1)"/>&nbsp;<b>:</b>&nbsp;' +
		'<input type="button" class="button" value="&lt;" onclick = "dateSelector.advanceMinute(-5)"/>' +
		'<select name="currentMinute" class="timeRolldown" onchange="dateSelector.changeMinute(this.options[this.selectedIndex].value)">' + minuteOptions + '</select>' +
		'<input type="button" class="button" value="&gt;" onclick = "dateSelector.advanceMinute(5)"/>' +
		'<input type="button" class="button okButton" value="OK" onclick="dateSelector.set();"/></td>' +
		'</tr>' ) :
		'') +

		'</table>';

	document.getElementById("calendarArea")['innerHTML'] = calendar;
}

this.set = function setDate(millis) {

	if (!millis && currentDate) {
		 millis =  currentDate.getTime();
	}

	if (currentDate) {
		millis = parseInt(millis) +
				(currentHour * 60 * 60 * 1000) +
				(currentMinute * 60 * 1000)	+
				(currentSecond * 1000);
	}

	currentElement.value = millis;
	document.getElementById("dateSelectorLabel_"+ currentElement.name)['innerHTML'] = millisToDateString(millis);
	hideDateSelector();
};

this.advanceMonth = function advanceMonth(delta) {
	currentMonth += delta;
	while (currentMonth < 0) {
		currentMonth += 12;
		currentYear--;
		}

	while (currentMonth >= 12) {
		currentMonth -= 12;
		currentYear++ ;
	}
	createCalendarArea();
};


this.advanceHour = function advanceHour(delta) {
	currentHour += delta;
	while (currentHour <  0) { currentHour += 24; }
	while (currentHour > 24) { currentHour -= 24; }
	createCalendarArea();
};

this.advanceMinute = function advanceMinute(delta) {
	currentMinute += delta;
	while (currentMinute <  0) { currentMinute += 60; }
	while (currentMinute > 60) { currentMinute -= 60; }
	createCalendarArea();
};

this.changeMonth = function changeMonth(month) {
	currentMonth = +month;
	createCalendarArea();
};

this.changeHour = function changeHour(hour) {
	currentHour = +hour;
};

this.changeMinute = function changeMinute(minute) {
	currentMinute = +minute;
};

function millisToDateString(millis) {
	if (!millis) { return ""; }

	var date = new Date(parseInt(millis));
	var dateString = date.toUTCString();

	// Remove time
	if (!showTimeSelector) {
		dateString = dateString.replace(/\d\d(:|\.)\d\d(:|\.)\d\d/, '');
		dateString = dateString.replace(/ (AM|PM)/i, '');
	}

	// Remove seconds
	dateString = dateString.replace(/(\d\d(:|\.)\d\d)(:|\.)\d\d/, '$1');

	// Remove weekday and prefix just to make string shorter
	dateString = dateString.replace(/^\w+, /, '');
	dateString = dateString.replace(/^(the|den) /i, '');

	// Remove GMT or UTC suffix
	dateString = dateString.replace(/ (GMT|UTC)/i, '');

	// Prevent linebreaks
	dateString = dateString.replace(/ /g, '&nbsp;');

	return dateString;
}

function writeSelectorHTML() {
	var selectorHTML =
		'<form action="#" method="get" name="dateSelectorForm" onsubmit="return false;">' +
		'<table id="dateSelector">' +
		'<tr><td id="calendarArea"></td></tr>' +
		'</table>' +
		'</form>';
	insertAdjacentHTML(document.body, "beforeEnd", selectorHTML);
}

function initDateSelector() {
	if (document.getElementById) {

		var forms = document.getElementsByTagName("form");
		for (var j = 0; j < forms.length; j++) {
			var inputs = forms[j].getElementsByTagName("input");
			for (var i = 0; i < inputs.length; i++) {
				if (inputs[i].className == "dateSelector" ||
					inputs[i].className == "dateTimeSelector") {

					showTimeSelector = inputs[i].className == "dateTimeSelector" ? true : false;

					var actionString = 'dateSelector.show(\'' + j + '\', \'' + inputs[i].name + '\', '+ showTimeSelector.toString() +' )';
					var formFieldHTML =
						'<table class="dateSelectorField" id="dateSelectorTable_'+ inputs[i].name +'" onclick="' + actionString + '">' +
						'<tr>' +
						'<td id="dateSelectorLabel_' + inputs[i].name + '" class="dateSelectorLabel">'+ millisToDateString(inputs[i].value) +'</td>' +
						'<td><img src="' + imagePath + 'calendar.gif" height="16" width="16" hspace="2" align="middle" border="0" alt="" /></td>' +
						'</tr>' +
						'</table>';

					insertAdjacentHTML(inputs[i], "afterEnd", formFieldHTML);
				}
			}
		}
	}
}


function getTop(obj) {
	var y = 0;
	do {
	y += obj.offsetTop;
	obj = obj.offsetParent;
	} while (obj !== null);

	return y;
}

function getLeft(obj) {
	var x = 0;
	do {
	x += obj.offsetLeft;
	obj = obj.offsetParent;
	} while (obj !== null);

	return x;
}

setEventByObject(document, 'click', hideDateSelector);

setEventByObject(window, 'load', initDateSelector);


}

// Overwrite the function reference with an object instance.
// Now this is the single point of contact with the rest of the javascript world.
// Our variables are now truly private and can't get owerwritten by others even by mistake.
dateSelector = new dateSelector();

