var CalendarGenerator = new Class({
	Implements: [Options, Events],
	
	options: {
		dayClass			:"day",
		yearClass			:"year",
		monthClass			:"month",
		monthPrefixClass	:"monthNum",
		dayPrefixClass		:"dayNum",
		yearPrefixClass		:"year",
		
		yearElement			:"div",
		monthElement		:"div",
		dayElement			:"div",			
		containerId			:"fullCalendar",
		
		paddedClass			: "padded",
		
		onDayGeneration		:$empty
	},
	
	years	: {},	
	months	: {},
	days	: {},
	
	
	initialize: function(CalendarObject, options)
	{
		this.setOptions(options);
		this.container = $(this.options.containerId);
		if($defined(CalendarObject))
		{
			this.generateCalendar(CalendarObject);
		}
	},
	
	reset: function()
	{
		this.years 	= {};
		this.months = {};
		this.days 	= {};
		this.container.set("html", "");
	},
	
	generateCalendar: function(CalendarObject)
	{
		this.reset();
		$H(CalendarObject).each(this.generateYear.bind(this));
	},	
	
	generateYear: function(yearObject, year)
	{
		if (!$defined(this.years[year])) 
		{
			this.years[year] = new Element(this.options.yearElement, {
				"class": this.options.yearClass + " " + this.options.yearPrefixClass + year
			}).inject(this.container);
		}
		
		$H(yearObject).each(function(monthObject, month){
			this.generateMonth(monthObject, month, year);
		}.bind(this));
	},
	
	generateMonth: function(monthObject, month, year)
	{
		if (!$defined(this.months[year + "/" + month])) {
			this.months[year + "/" + month] = new Element(this.options.monthElement, {
				"class": this.options.monthClass + " " + this.options.monthPrefixClass + month
			}).inject(this.years[year]);
			
			new Element("h3", {
				text: monthObject.monthName + " " + year + ""
			}).inject(this.months[year + "/" + month]);
		
			$H(monthObject.days).each(function(dayObject, timestamp){
				this.generateDays(dayObject, timestamp, month, year);
			}.bind(this));
		}
	},
	
	addCalendar: function(calendar)
	{
		$H(calendar).each(this.generateYear.bind(this));
	},
	
	generateDays: function(dayObject, timestamp, month, year)
	{
		if(!$defined(this.days[timestamp]))
		{
			this.days[timestamp] = [];
		}
		
		var paddedClass = "";
		
		var isPadded = dayObject.month != month;
		
		if(isPadded)
		{
			paddedClass = this.options.paddedClass+" ";
		}
		
		var day = new Element(this.options.dayElement, {"class":paddedClass+this.options.dayClass+" "+this.options.dayPrefixClass+dayObject.weekDay, alt:timestamp});
		day.inject(this.months[year+"/"+month]);
		this.days[timestamp].push(day);
	
		if(isPadded)
		{
			day.setStyle("opacity", ".35");
		}
		
		new Element("span", {text:dayObject.monthDay}).inject(day);
		
		this.fireEvent("onDayGeneration", [timestamp, day, dayObject]);
	},
	
	getDays: function()
	{
		return this.days;
	}
});