			
Event.observe(window,'load', function() 
{
	var dateDialog = new CalendarDialog($('calendar-dialog'));
	
	var inputFrom = $('input_from');
	var inputTill = $('input_till');
	
	$A(['from', 'till']).each(function(t) {
		var input = $('input_' + t);
		var link = $('link_' + t);
		
		input.setDate = function(date)
		{
			if (date == null)
			{
				this.value ='';
			}
			else
			{
				this.value = date.getDate() + ' / ' + (date.getMonth() + 1) + ' / ' + date.getFullYear();
			}
		};
		
		input.getDate = function(date)
		{
			if (this.value.length > 0)
			{
				var p = this.value.split(" / ");
				var date = new Date();
				date.setDate(1);
				date.setMonth(p[1] - 1);
				date.setYear(p[2]);
				date.setDate(p[0]);
				
				return date;
			}
			else
			{
				return null;
			}
		}
		
		input.onfocus = function()
		{
			this.blur();
		}

		Event.observe(link, 'click', datePopupHandler);
		Event.observe(input, 'click', datePopupHandler);
		
		function datePopupHandler(event)
		{
			Event.stop(event);
				
				dateDialog.dateListener = function(date)
				{
					if (date && DateUtil.compare(new Date(), date) == 1)
					{
						alert("U kunt geen datum in verleden kiezen.");
						return;	
					}
					
					input.setDate(date);
					
					if (date !== null)
					{
						if (t == 'from' && inputTill.getDate() !== null && DateUtil.compare(inputTill.getDate(), date) < 0)
						{
							inputTill.setDate(date);
						}
						else if (t == 'till' && inputFrom.getDate() !== null && DateUtil.compare(inputFrom.getDate(), date) > 0)
						{
							inputFrom.setDate(date);
						}
					}
					
					dateDialog.hide();
				}
				
				var date = input.getDate();
				
				if (date == null)
				{
					var paneDate = (t == 'till' && inputFrom.getDate())
						? inputFrom.getDate()
						: new Date();
						
					dateDialog.setPaneDate(paneDate);
				}
				else
				{
					dateDialog.setDate(date);
				}
					
				dateDialog.show(input);
		}
	});
});
			
var DateUtil = {
	
	daysInMonth: function(date)
	{
		var dd = new Date(date);
		dd.setDate(1);
		dd.setMonth(dd.getMonth() + 1);
		dd.setDate(0);
		return dd.getDate();
	},
	
	compare: function(a, b)
	{
		var ret = 0;
		$A(['getFullYear', 'getMonth', 'getDate']).each(function(method) {
			var av = a[method].apply(a);
			var bv = b[method].apply(b);
			
			if (av != bv)
			{
				ret = av > bv ? 1 : -1;
				throw $break;
			}
		});
		
		return ret;
	}
}

var CalendarDialog = Class.create({
	
	initialize: function(element)
	{
		this.element = element;
		this.calendarBody = element.select('table.calendar TBODY').first();
		
		this.paneDate = null;
		this.showing = null;
		
		this.today = new Date();
		this.today.equals = function(o)
		{
			return this.getYear() == o.getYear()
				&& this.getMonth() == o.getMonth()
				&& this.getDate() == o.getDate();
		}
		
		var self = this;
								
		// assign links
		$A(['prev', 'next']).each(function (direction) {
			var label = 'link-' + direction;
			var link = element.select('A.' + label).first();
			Event.observe(link, 'click', function(event) {
				
				Event.stop(event);
				
				var month = (direction == 'prev') 
					? -1 : 1;
				
				var date = new Date(self.paneDate);
				date.setMonth(date.getMonth() + month);
				self.updatePane(date);
			});
		});
		
		this.selectYear = element.select('SELECT[name="year"]').first();
		this.selectMonth = element.select('SELECT[name="month"]').first();
		
		$A([this.selectYear, this.selectMonth]).each(function (select) {
			select.setSelected = function(value)
			{
				$A(this.options).each(function(o) {
					if (o.value == value)
					{
						o.selected = true;
						throw $break;
					}
				});
			};
			
			select.getSelected = function()
			{
				return this.options[this.selectedIndex].value;	
			};
			
			select.onchange = function()
			{
				var date = new Date(self.paneDate);
				date.setDate(1);
				date.setMonth(self.selectMonth.getSelected() - 1);
				date.setYear(self.selectYear.getSelected());
				
				self.updatePane(date);
			};
		});
		
		Event.observe(document, 'click', function(event) {
			if (! self.showing)
				return;
				
			if (! $(Event.element(event)).up('.calendar-dialog'))
			{
				self.hide();
			}
		})
		
		Event.observe(element.select("A#null").first(), 'click', function(event) {
			Event.stop(event);
			
			if (self.dateListener)
				self.dateListener(null);
		})
	},
	
	_getDateString: function(date)
	{
		return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
	},
	
	_createDay: function(date)
	{
		var strDate = this._getDateString(date);

		var td = new Element('td', { rel: strDate });
		td.update(date.getDate());
		
		if (this.today.equals(date))
			td.addClassName('today');
			
		Event.observe(td, 'mouseover', function() { this.addClassName('hover'); });
		Event.observe(td, 'mouseout', function() { this.removeClassName('hover'); });
		
		var self = this;
		
		Event.observe(td, 'click', function() { 
			var p = this.getAttribute('rel').split("-");
		
			var date = new Date();
			date.setDate(1);
			date.setYear(p[0]);
			date.setMonth(p[1] - 1);
			date.setDate(p[2]);
			
			if (self.dateListener)
				self.dateListener(date);
		});
		
		return td;
	},
	
	updatePane: function(date)
	{
		// check whether it is necessary to update the pane
		if (this.paneDate && this.paneDate.getMonth() == date.getMonth() && this.paneDate.getFullYear() == date.getFullYear())
			return;
		
		this.paneDate = date;
		
		// remove all elements from the body
		this.calendarBody.childElements().each(function(node) {
			$(node).remove();
		});
		
		// adjust the selects
		this.selectMonth.setSelected(date.getMonth() + 1);
		this.selectYear.setSelected(date.getFullYear());
		
		var first = new Date(date);
		first.setDate(1);
		
		var firstDay = (! first.getDay())
			? 6
			: first.getDay() - 1;
			
		var i = 0;
		
		var tableTr = new Element('tr');
		this.calendarBody.appendChild(tableTr);

		var dayDate = new Date(date);
		dayDate.setDate(1);
		
		if (firstDay > 0)
		{
			var prevDate = new Date(date);
			prevDate.setDate(1);
			prevDate.setMonth(prevDate.getMonth() - 1);
			
			var lastDay = DateUtil.daysInMonth(prevDate);

			while (firstDay)
			{
				prevDate.setDate(lastDay - (firstDay - 1));

				var td = this._createDay(prevDate);
				td.addClassName('gray');
				tableTr.insert(td);
				
				i++;
				firstDay--;
			}
		}
		
		dayDate.setDate(1);
		dayDate.setMonth(date.getMonth());
		
		for (var day = 1; day <= DateUtil.daysInMonth(date); day++)
		{
			if ((i % 7) == 0)
			{
				tableTr = new Element('tr');
				this.calendarBody.appendChild(tableTr);
			}
			
			dayDate.setDate(day);
			
			var td = this._createDay(dayDate);
			tableTr.insert(td);
			
			i++;
		}
		
		var day = 1;
		dayDate.setDate(day);
		dayDate.setMonth(dayDate.getMonth() + 1);
		
		while (i % 7)
		{
			var td = this._createDay(dayDate);
			td.addClassName('gray');
			
			tableTr.insert(td);
			
			++i;
			dayDate.setDate(++day);
		}
	},
	
	setPaneDate: function(date)
	{
		this.updatePane(date);
	},
	
	setDate: function(date)
	{
		this.updatePane(date);
		
		var str = this._getDateString(date);
		
		var selected = this.calendarBody.select('TD[rel="' + str + '"]').first();
		selected.addClassName('selected');
	}
	
	,show: function(relative)
	{
		var p = relative.positionedOffset();
		this.element.style.left = p[0] + 'px';
		this.element.style.top = p[1] + relative.offsetHeight + 2 + 'px';
		
		this.element.show();
		
		this.showing = true;
	}
	
	,hide: function()
	{
		this.element.hide();
		this.paneDate = null;
		
		this.showing = false;
	}
});
