module.exports = new Class({
	Extends: Htk.Field
	,Tag: 'htk-calendar'
	,Properties:
	{
		restrictFunc:
		{
			type: Function
			,set: function(x) {
				this._restrictFunc = x;
			}
			,get: function(x) {
				return this._restrictFunc;
			}
		}
	}
	
	,cells: []
	,selectedCell: -1
	,year: null
	,month: null

	,render: function() {
		var len = Vn.Date.WDays.length;
		
		var node = this.createRoot('div');
		node.className = 'htk-calendar';
		
		var table = this.createElement('table');
		this.node.appendChild(table);

		var colgroup = this.createElement('colgroup');
		table.appendChild(colgroup);
		
		for (var i = 0; i < len; i++)
			colgroup.appendChild(this.createElement('col'));
		
		var thead = this.createElement('thead');
		table.appendChild(thead);

		var tr = this.createElement('tr');
		thead.appendChild(tr);

		var th = this.createElement('th');
		th.appendChild(this.createTextNode('<'));
		th.className = 'button';
		th.addEventListener('click', this.prevMonthClicked.bind(this));
		tr.appendChild(th);

		var th = this.createElement('th');
		th.colSpan = 5;
		tr.appendChild(th);

		var monthNode = this.createElement('span');
		th.appendChild(monthNode);

		var space = this.createTextNode(' ');
		th.appendChild(space);
		
		var yearNode = this.createElement('span');
		th.appendChild(yearNode);

		var th = this.createElement('th');
		th.appendChild(this.createTextNode('>'));
		th.className = 'button';
		th.addEventListener('click', this.nextMonthClicked.bind(this));
		tr.appendChild(th);
		
		var tr = this.createElement('tr');
		thead.appendChild(tr);
		
		for (var i = 1; i <= len; i++) {
			var th = this.createElement('th');
			tr.appendChild(th);
			
			var weekday = _(Vn.Date.AbrWDays [i%len]);
			th.appendChild(this.createTextNode(weekday));
		}

		var tbody = this.createElement('tbody');
		table.appendChild(tbody);
		
		for (var i = 0; i < 6; i++) {
			var tr = this.createElement('tr');
			tbody.appendChild(tr);

			for (var j = 0; j < len; j++) {
				var td = this.createElement('td');
				td.addEventListener('click', this.dayClicked.bind(this, td, i*len+j));
				tr.appendChild(td);
				
				var div = this.createElement('div');
				td.appendChild(div);

				this.cells.push({
					node: div,
					enabled: false,
					day: -1
				});
			}
		}

		this.monthNode = monthNode;
		this.yearNode = yearNode;
		this.goToCurrentMonth();
	}

	,getMonthDays: function() {
		if (this.month > 6)
			return (this.month % 2 != 0) ? 31 : 30;
		else if (this.month != 1)
			return (this.month % 2 != 1) ? 31 : 30;
		else
			return (this.year % 4 != 0) ? 28 : 29;
	}
	
	,goToMonth: function(year, month) {
		if (year)
			this.year = year;
		if (!isNaN(month))
			this.month = month;

		this.refresh();
	}
	
	,goToSelectedMonth: function() {
		var date = this._value;
		
		if (date instanceof Date)
			this.goToMonth(date.getFullYear(), date.getMonth());
		else
			this.goToCurrentMonth();			
	}

	,goToCurrentMonth: function() {
		var date = new Date();
		this.goToMonth(date.getFullYear(), date.getMonth());
	}

	,refresh: function() {
		Vn.Node.setText(this.yearNode, this.year);
		Vn.Node.setText(this.monthNode, _(Vn.Date.Months[this.month]));

		var day = 1;
		var cellDate = new Date(this.year, this.month, 1);

		var weekDay = cellDate.getDay();
		var firstWeekDay = (weekDay != 0) ? weekDay - 1 : 6;
		var monthDays = this.getMonthDays();

		for (var i = 0; i < this.cells.length; i++) {
			var cell = this.cells[i];

			if (firstWeekDay <= i && day <= monthDays) {
				Vn.Node.setText(cell.node, day);
				cell.enabled = true;
				cell.day = day++;
				
				if (this._restrictFunc) {
					cell.enabled = this._restrictFunc(cellDate);
					cellDate.setDate(cellDate.getDate() + 1);
				}
			} else {
				Vn.Node.removeChilds(cell.node);
				cell.enabled = false;
				cell.day = -1;
			}
			
			cell.node.className = cell.enabled ? 'enabled' : 'disabled';
		}

		// Marks the current day

		var today = new Date();
		
		if (this.year == today.getFullYear()
		&& this.month == today.getMonth()) {
			var cellIndex = (firstWeekDay + today.getDate()) - 1;
			Vn.Node.addClass(this.cells[cellIndex].node, 'today');
		}
		
		// Marks the selected day
		
		var date = this._value;

		if (date instanceof Date
		&& this.year == date.getFullYear()
		&& this.month == date.getMonth())
			this.selectCell((firstWeekDay + date.getDate()) - 1);
		else
			this.selectCell(-1);
	}

	,selectCell: function(cellIndex) {
		if (this.selectedCell != -1) {
			var node = this.cells[this.selectedCell].node;
			Vn.Node.removeClass(node, 'selected');
		}
		if (cellIndex != -1) {
			var node = this.cells[cellIndex].node;
			Vn.Node.addClass(node, 'selected');
		}

		this.selectedCell = cellIndex;
	}

	,putValue: function() {
		this.goToSelectedMonth();
	}

	,dayClicked: function(td, cellIndex) {
		var cell = this.cells[cellIndex];
	
		if (cell.enabled) {
			this.selectCell(cellIndex);

			var newDate = new Date(this.year, this.month, cell.day);

			if (this.value) {
				var orgDate = this.value instanceof Date
					? this.value
					: new Date(this.value);

				newDate.setHours(
					orgDate.getHours(),
					orgDate.getMinutes(),
					orgDate.getSeconds(),
					orgDate.getMilliseconds()
				);
			}

			this.valueChanged(newDate);
		}
	}

	,prevMonthClicked: function() {
		if (this.month > 0)
			this.month--;
		else {
			this.month = 11;
			this.year--;
		}
		
		this.refresh();
	}

	,nextMonthClicked: function() {
		if (this.month < 11)
			this.month++;
		else {
			this.month = 0;
			this.year++;
		}
		
		this.refresh();
	}
});