Element.implement({
	getSelectedValue: function() {
		if(this.tagName.toLowerCase()!='select')
			return null;
		return $splat(new Elements($A(this.options).filter(function(option) {
			return option.selected;
		})).map(function(opt) {
			return opt.value.clean();
		}));
	},
 
	getSelectedIndex: function() {
		if(this.tagName.toLowerCase()!='select')
			return null;
		return $splat(new Elements($A(this.options).filter(function(option) {
			return option.selected;
		})).map(function(opt) {
			return opt.index;
		}));
	},
 
	getSelectedFull: function() {
		if(this.tagName.toLowerCase()!='select')
			return null;
		return $splat(new Elements($A(this.options).filter(function(option) {
			return option.selected;
		})).map(function(opt) {
			return {
				'index': opt.index,
				'value': opt.value.clean()
			};
		}));
	},
 
	setSelected: function(data, add) {
		if(this.tagName.toLowerCase()!='select')
			return null;
		if(!add)
			this.clearSelect();
		var data = $splat(data);
		Array.each(this.options, function(option, i) {
			if(data.contains(option.getProperty('value')) || data.contains(i))
				option.set('selected', 'selected');
		});
		return;
	},
 
	clearSelect: function(ds) {
		if(this.tagName.toLowerCase()!='select')
			return null;
		var ls = this.getSelectedFull();
		Array.each(this.options, function(option) {
			option.set('selected', (option.defaultSelected && ds) ? 'selected' : '');
		});
		return ls;
	}
});

(function(){
	var events;
	var check = function(e){
		var target = $(e.target);
		var parents = target.getParents();
		events.each(function(item){
			var element = item.element;
			if (element != target && !parents.contains(element))
				item.fn.call(element, e);
		});
	};
	Element.Events.outerClick = {
		onAdd: function(fn){
			if(!events) {
				document.addEvent('click', check);
				events = [];
			}
			events.push({element: this, fn: fn});
		},
		onRemove: function(fn){
			events = events.filter(function(item){
				return item.element != this || item.fn != fn;
			}, this);
			if (!events.length) {
				document.removeEvent('click', check);
				events = null;
			}
		}
	};
})();

var DatePicker = new Class({
	
	element:null,
	picker: false,
	currentDate : new Date(),
	startDate: null,
	endDate: null,
	doNotDestroy: false,
	monthNames: [
		'Januar', 'Februar', 'März',
		'April', 'Mai', 'Juni',
		'Juli', 'August', 'September',
		'Oktober', 'November', 'Dezember'
	],
	dayNames: ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Sonnabend', 'Sonntag'],
	
	initialize: function(start, end)
	{
		this.startDate = start;
		this.endDate = end;
	},
	
	show: function(element) {
		this.element = element;
		this.setValue(element.value);
		if(!this.picker)
		{
			this.createPicker();
			var that = this;
			(function() {
				that.picker.addEvent('outerClick', function(e) {
					this.hide();
				}.bindWithEvent(that));
			}).delay(100);
		}
		else
		{
			this.update();
			this.doNotDestroy = true;
		}
		this.picker.inject($(element), 'after');
		this.picker.setStyle('display', 'block');
		
	},
	update: function()
	{
		var m = this.picker.getElementById('date-picker-month');
		m.setSelected(this.currentDate.getMonth());
		var y = this.picker.getElementById('date-picker-year');
		y.setSelected(this.currentDate.getFullYear());
		var tbody = this.dateCells(this.currentDate);
		tbody.replaces(this.picker.getElement('tbody'));
	},
	
	hide: function(element) {
		if(!this.doNotDestroy)
		{
			this.picker.removeEvent('outerClick');
			this.picker.destroy();
			this.picker = false;
		}
		this.doNotDestroy = false;
	},
	
	createPicker: function()
	{
		var div = new Element('div', {
			'id':'chartDatePicker',
			'styles':{
				'position':'absolute',
				'width':140
			}
		});
		var table = new Element('table', {
			'styles':{
				'width':'100%',
				'table-layout':'fixed'
			}
		});
		
		var thead = new Element('thead');
		
		var row1 = new Element('tr');
		var that = this;
		var month = new Element('td', {'colspan': 4}).grab(
			new Element('select', {
				'id' : 'date-picker-month',
				'html': this.monthOptions(),
				'styles':{
					'font':'10px Arial, Helvetica, sans-serif'
				},
				'events': {
					'change': function() {
						that.updateDateCells(this.value, 'month');
					}
				}
			})
		);
		var year = new Element('td', {'colspan': 3}).grab(
			new Element('select', {
				'id' : 'date-picker-year',
				'html': this.yearOptions(),
				'styles':{
					'font':'10px Arial, Helvetica, sans-serif'
				},
				'events': {
					'change': function() {
						that.updateDateCells(this.value, 'year');
					}
				}
			})
		);
		row1.adopt(month, year);
		
		var row2 = this.dayNameRow();
		
		thead.adopt(row1, row2);
		
		var tbody = this.dateCells(this.currentDate);
		
		div.grab(table.adopt(thead, tbody));
		
		this.picker = div;
	},
	
	monthOptions: function()
	{
		var out = '', cMonth = this.currentDate.getMonth();
		for(var i=0; i<12; ++i)
		{
			out += '<option value="'+i+'"';
			if(i == cMonth)
			{
				out += ' selected="selected"';
			}
			out += '>'+this.monthNames[i]+'</option>';
		}
		return out;
	},
	
	yearOptions: function()
	{
		var out = '', cYear = this.currentDate.getFullYear();
		for(var i=this.startDate.getFullYear(), j=this.endDate.getFullYear(); i<=j; ++i)
		{
			out += '<option value="'+i+'"';
			if(i == cYear)
			{
				out += ' selected="selected"';
			}
			out += '>'+i+'</option>';
		}
		return out;
	},
	
	dayNameRow: function()
	{
		var out='';
		var row = new Element('tr');
		for(var i=0; i<7; ++i)
		{
			row.grab(new Element('th', {
				'html': this.dayNames[i].substr(0,1),
				'styles':{
					'text-align':'center',
					'font-weight':'bold'
				}
			}));
		}
		return row;
	},
	
	dateCells: function(calcDate)
	{
		var tbody = new Element('tbody');
		
		var row = new Element('tr');
		calcDate.setDate(1);
		var day = calcDate.getDay();
		var weekday = (day + 7 - 1) % 7;
		
		if(weekday > 0)
		{
			var numdayslastmonth = this.daysInMonth((calcDate.getMonth() - 1), calcDate.getFullYear());
			console.log(numdayslastmonth);
			for(var i=weekday; i>0; --i)
			{
				//calcDate.setDate(weekday - i);
				row.grab(new Element('td', {
					'html' : (numdayslastmonth - i + 1),
					'class' : 'prev-month',
					'styles':{'text-align':'center'}
				}));
			}
		}
		
		var checkDate = new Date(calcDate.getFullYear(),calcDate.getMonth());
		
		for(var i=1, daysinmonth = this.daysInMonth(calcDate.getMonth(), calcDate.getFullYear()); i<=daysinmonth; i++, weekday++)
		{
			checkDate.setDate(i);
			
			if(weekday == 7)
			{
				weekday = 0;
				tbody.grab(row);
				row = new Element('tr');
			}
			var td = new Element('td', {'html':i, 'styles':{'text-align':'center'}});
			var classNames = [];
			if(weekday == 5 || weekday == 6)
			{
				classNames.push('weekend');
			}
			if(checkDate < this.startDate || checkDate >this.endDate)
			{
				classNames.push('off');
			}
			else
			{
				td.addEvent('click', function(e) {
					this.updateElement(e.target.get('html'));
				}.bindWithEvent(this));	
			}
			td.set('class', classNames.join(' '));
			
			row.grab(td);
		}
		if(weekday != 7)
		{
			for(var i=1; i<=(7-weekday); ++i)
			{
				var td = new Element('td', {'html':i, 'class': 'next-month', 'styles':{'text-align':'center'}});
				row.grab(td);
			}
		}
		
		tbody.grab(row);
		
		return tbody;
	},
	
	updateElement:function(num){
		
		this.currentDate.setDate(num);
		var string = formatDate(this.currentDate);
		this.element.value = string;
		this.hide();
		setRange();
	},
	
	updateDateCells:function(val, what)
	{
		if(what == 'year')
		{
			this.currentDate.setFullYear(val);
		}
		else
		{
			this.currentDate.setMonth(val);
		}
		var tbody = this.dateCells(this.currentDate);
		tbody.replaces(this.picker.getElement('tbody'));
	},
	
	
	daysInMonth: function(month, year)
	{
		var d = new Date(year, month+1, 0);

		return d.getDate();
	},
	
	setValue: function(string)
	{
		var a = string.split('.');
		this.currentDate.setFullYear(a[2]);
		this.currentDate.setMonth(a[1] - 1);
		this.currentDate.setDate(a[0]);
		
	}
	
});