function monthIndexToName(index) {
	switch (index){
		case 0: return "January"; break;
		case 1: return "February"; break;
		case 2: return "March"; break;
		case 3: return "April"; break;
		case 4: return "May"; break;
		case 5: return "June"; break;
		case 6: return "July"; break;
		case 7: return "August"; break;
		case 8: return "September"; break;
		case 9: return "October"; break;
		case 10: return "November"; break;
		case 11: return "December"; break;
	}	
}

function daysInMonth(year, month) {
	var date = new Date(year, month, 1);
	var result = 0;
	
	while (month == date.getMonth()) {
		date.setDate(date.getDate() + 1);
		result++;								
	}
	
	return result;	
}

function HTMLTable() {
	this.table = document.createElement('table');

	this.addRow = function(row) {
	    var tableBody = document.createElement('tbody');

	    tableBody.appendChild(row);

	    this.table.appendChild(tableBody);
	} 
	
	this.render = function() {
		return this.table;
	} 
}

function HTMLTableRow() {
	this.row = document.createElement('tr'); 
	
	this.addTableData = function (tableData) {
		this.row.appendChild(tableData);
	}
	
	this.addArrayAsRow = function (array) {
		var tableData;
		
        for (var i = 0; i < array.length; i++) {
        	newtableData = new HTMLTableData();
        	newtableData.setHTML(array[i]); 
			
			this.addTableData(newtableData.render());
        }	
	} 
	
	this.render = function () {
		return this.row;
	} 	
}

function HTMLTableData() {
	this.tableData = document.createElement('td');
	
	this.setHTML = function (html) {
		this.tableData.innerHTML = html;		
	}
	
	this.setOnClick = function (onclick) {
		this.tableData.onclick = onclick;
	}
	
	this.render = function () {
		return this.tableData;
	}
}

function newLink() {
	return document.createElement('a');
}

function newSpan() {
	return document.createElement('span');
}

function newDiv() {
	return document.createElement('div');
}

function DateSelectorPage (targetInputField, year, month) {
	this.targetInputField = targetInputField;
	this.year = year;
	this.month = month;
	this.daysInMonth = daysInMonth(year, month);
	this.startDay = new Date(year, month, 1).getDay();
	this.hour = new Date().getHours();
	this.minutes = new Date().getMinutes();
	
	this.headerRow = function () {
		var row = new HTMLTableRow();
		
		row.addArrayAsRow(new Array("s", "m", "t", "w", "t", "f", "s"));
		
		return row.render();
	}
	
	this.daysArray = function () {
		var array = new Array(42);
		var dayCounter = 1;
		
        for (i = 0; i < this.startDay; i++) {
			array[i] = "-";
        }	
        
        for (i = this.startDay; i < (this.startDay + this.daysInMonth); i++) {
			array[i] = dayCounter;
			dayCounter++;
        }	
       
        for (i = (this.startDay + this.daysInMonth); i < array.length; i++) {
			array[i] = "-";
        }	
        
        return array;
	}

	this.setDate = function(dayIndex) {
	    var monthText = this.month + 1;
	    var hourText = this.hour;
	    var minutesText = this.minutes;
	    var dayText = dayIndex;

	    if (monthText < 10) {
	        monthText = "0" + monthText;
	    }
	    if (dayText < 10) {
	        dayText = "0" + dayText;
	    }
	    if (hourText < 10) {
	        hourText = "0" + hourText;
	    }
	    if (minutesText < 10) {
	        minutesText = "0" + minutesText;
	    }

	    this.targetInputField.value = this.year + "-" + monthText + "-" + dayText + " " + hourText + ":" + minutesText + ":00";
	}
	
	this.handleDateClick = function(dayIndex) {
		var page = this;
		
		return function () {
			page.setDate(dayIndex);
		}
	}

	this.render = function() {
	    var table = new HTMLTable();
	    var row;
	    var tableData;
	    var daysArray;
	    var i = 0;

	    table.table.className = "dateSelectorTable";
	    table.addRow(this.headerRow());

	    row = new HTMLTableRow();
	    daysArray = this.daysArray();

	    while (i < daysArray.length) {
	        row = new HTMLTableRow();

	        for (j = 0; j < 7; j++) {
	            tableData = new HTMLTableData();
	            tableData.setHTML(daysArray[i + j]);

	            if (daysArray[i + j] > 0) {
	                tableData.setOnClick(this.handleDateClick(daysArray[i + j]));
	            }

	            row.addTableData(tableData.render());
	        }

	        table.addRow(row.render());

	        i += 7;
	    }

	    return table.render();
	}
}

function DateSelector (targetInputField) {
	this.targetInputField = targetInputField;
	this.element = document.createElement('div');
	this.currentDate = new Date(); 
	this.currentNode;

	this.handleClickChangeMonthEvent = function (link, index) {
		var dateSelector = this;
	
		return function () {
			dateSelector.changeMonth(index);
			dateSelector.refresh();
		}
	}
	
	this.currentMonth = function () {
		return this.currentDate.getMonth();
	} 
	
	this.currentYear = function () {
		return this.currentDate.getFullYear();
	} 

	this.changeMonth = function (index) {
		this.currentDate.setMonth(this.currentDate.getMonth() + index);
	}

	this.header = function () {
		var span = newSpan();
		var backward = newLink();
		var caption = newLink(); 
		var forward = newLink();

		span.className = "dateSelectorHeader";
			
		backward.innerHTML = "&lt;";
		backward.onclick = this.handleClickChangeMonthEvent(backward, -1);
		backward.className = "backward";
		
		forward.innerHTML = "&gt;";
		forward.onclick = this.handleClickChangeMonthEvent(forward, 1);
		forward.className = "forward";
		
		caption.innerHTML = this.currentYear() + " " + monthIndexToName(this.currentMonth()); 
		caption.className = "caption";
			
		span.appendChild(backward);
		span.appendChild(caption); 
		span.appendChild(forward);	
		
		return span;
	}

	this.showMonth = function () {
		var result = newDiv(); 
		var page = new DateSelectorPage(this.targetInputField, this.currentYear(), this.currentMonth());
		
		result.appendChild(this.header());
		result.appendChild(page.render());
		return result;
	}

	this.refresh = function () {
		var newNode = this.showMonth();
		
		this.element.replaceChild(newNode, this.currentNode);
		this.currentNode = newNode;
	}

 	this.create = function () {
		this.element.className = "dateSelector";
		this.element.style.display = "none";

		this.currentNode = this.showMonth();
		this.element.appendChild(this.currentNode);
	}
	
	this.showOrHide = function () {
		if (this.element.style.display == "block") {
			this.element.style.display = "none";
		}
		else {
			this.element.style.display = "block";	
		}
	}

	this.create();
}

function DateSelectorField (identifier) {
	this.identifier = identifier;
	this.containingElement;
	this.selector; 

	this.createSelector = function () {
		this.containingElement = document.getElementById(identifier);
		this.containingElement.className = "dateSelectionField";

		this.selector = new DateSelector(this.containingElement.getElementsByTagName("input")[0]);

		this.containingElement.appendChild(this.selector.element);			
	}

	this.handleClick = function () {
		if (this.selector == null) {
			this.createSelector();
		}
	
		this.selector.showOrHide();
	}
}
