var Calendar = Class.create(
{
	initialize: function(inElement, inOptions)
	{
		this.element = $(inElement);
		
		if(!this.element)
		{
			return;
		}
		
		this.options = {
			dayClass: 'day',
			dragClass: null,
			onChange: null
		};
	
		Object.extend(this.options, inOptions);

		// -------
		
		var calendarID = "calendar_"+ this.element.identify();

		this.calendarElement = $(calendarID);
		
		if(!this.calendarElement)
		{
			this.calendarElement = this.element.insert({before: "<input type='hidden' name='" + calendarID + "'>"}).previous();
		}
		
		// -------
		
		var calendarChangeID = "calendarchange_" + this.element.identify();
		
		this.calendarChange = $(calendarChangeID);
		
		if(!this.calendarChange)
		{
			this.calendarChange = this.element.insert({before: "<input type='hidden' name='" + calendarChangeID + "'>"}).previous();
		}

		// -------
		
		this.today = $(this.element.identify() + "_today");
		this.next = $(this.element.identify() + "_next");
		this.previous = $(this.element.identify() + "_previous");
		this.month = $(this.element.identify() + "_month");
		this.year = $(this.element.identify() + "_year");
		
		if(this.today)
		{
			this.today.observe('click', this.click.bindAsEventListener(this));
		}
		
		if(this.next)
		{
			this.next.observe('click', this.click.bindAsEventListener(this));
		}
		
		if(this.previous)
		{
			this.previous.observe('click', this.click.bindAsEventListener(this));
		}
		
		if(this.month)
		{
			this.month.observe('change', this.change.bindAsEventListener(this));
		}
		
		if(this.year)
		{
			this.year.observe('change', this.change.bindAsEventListener(this));
		}

		this.update(this.month.value, this.year.value);
		
		// --------
		
		if(this.options.dragClass)
		{
			new Draggable(this.element, {
				select: this.options.dragClass,
				scroll: this.options.scroll,
				bounds: this.options.scroll
			});
			
			new Droppable(inElement, {
				select: this.options.dayClass,
				accept: this.options.dragClass,
				containment: this.element,
				onDrop: this.drop.bind(this)
			});
		}
	},
	
	drop: function(inEvent, inSource, inTarget)
	{
		this.calendarChange.value = inSource.identify() + "," + inTarget.identify();
		
		if(this.options.onChange)
		{
			this.options.onChange(this.month.value, this.year.value);
		}
	},
	
	click: function(inEvent)
	{
		var element = $(inEvent.element());
	
		if(element == this.today || element.up() == this.today)
		{
			var today = new Date();
			
			var year = today.getFullYear();
			var month = today.getMonth();
			
			this.update(month, year, true);
		}
		else if(element == this.next || element.up() == this.next)
		{
			var year = this.year.value;
			var month = this.month.value;

			month++;
			
			if(month > 11)
			{
				month = 0;
				year++;
			}
			
			this.update(month, year, true);
		}
		else if(element == this.previous || element.up() == this.previous)
		{
			var year = this.year.value;
			var month = this.month.value;
			
			month--;
			
			if(month < 0)
			{
				month = 11;
				year--;
			}
			
			this.update(month, year, true);
		}
	},
	
	change: function(inEvent)
	{
		var year = this.year.value;
		var month = this.month.value;
		
		this.update(month, year, true);
	},
	
	update: function(inMonth, inYear, inChanged)
	{
		if(!inMonth && inMonth != 0)
		{
			inMonth = this.month.value;
		}
		
		if(!inYear)
		{
			inYear = this.year.value;
		}
		
		this.calendarElement.value = inMonth + "," + inYear + (inChanged ? ",true" : "");
		
		if(this.options.onChange)
		{
			this.options.onChange(inMonth, inYear);
		}
	}
});