function Calendar() {
	$("calendar").addClassName("ajaxed");
	this.url = window.location.href.split(/[\?#]/).shift(); // base url	
	var parts = window.location.href.split(/[\?]/);
	this.initial_state = parts.length > 1 ? parts.pop() : "root"; // initial state is only determined by a query string. # bookmarks are dealt with another way
	this.cache.set(this.initial_state, $(this.content_id).innerHTML);
	this.em = new EventManager();
	this.initialize();
	// check if we have a bookmark
	var parts = window.location.href.split(/#/);
	if(parts.length > 1) {
		var newLocation = parts.pop();
		this.stateChange(newLocation, false);
	}
}
Calendar.prototype = {
	content_id: 'calendar',
	em: null,
	url: null,
	initial_state: null,
	cache: new Hash(),
	initialize: function() {
		$('manual_select').remove();
		new Autocompleter.SelectBox($('month_select'), {
			postFire: ':change'
		});
		new Autocompleter.SelectBox($('year_select'), {
			postFire: ':change'
		});
		new Autocompleter.SelectBox($('category_select'), {
			postFire: ':change'
		});
		new Autocompleter.SelectBox($('region_select'), {
			postFire: ':change'
		});
		$('month_select_combo').show();
		$('year_select_combo').show();
		$('category_select_combo').show();
		$('region_select_combo').show();
		this.addEvents();
		this.em.start();
		this.startCaching();
	},
	reset: function() {
		this.em.unset();
		this.initialize();
	},
	addEvents: function() {
		var main_action = this.dispatchStateChange.bind(this);
		$$('form.calendar_update input[type="submit"]').each(function(el){
			this.em.set(el.identify(), {
				click: main_action,
				_click: main_action,
				_cache: this.grab.bind(this, true)
			})
		}, this)
		$$('input.calendar_update').each(function(el) {
			this.em.set(el.identify(), {
				_change: main_action
			})
		}, this)
		$$('a.calendar_update').each(function(a) {
			this.em.set(a.identify(), {
				click: main_action
			})
		}, this)
		$$('table.calendar td.day').each(function(td) {
			this.em.set(td.identify(), {
				click: function(el) {
					if(el.tagName.toLowerCase() != "td") el = el.up("td");
					var down = el.down("input");
					$(down).fire("click");
				}.bindAsEventListener(this)
			})			
		}, this);
		$$("table.calendar td.day a").each(function(a) {
			this.em.set(a.identify(), {
				click: function(url, anchor) {
					anchor.up("td").down("input").fire("click");
				}
			})
		}, this);
	},
	stateChange: function(newLocation, is_new) {
		if(newLocation.length == 0) newLocation = this.initial_state; // if newLocation is blank, return to inital state
		var html = this.grab(false, newLocation, this.updateCalendar.bind(this, newLocation, is_new));
	},
	updateCalendar: function(newLocation, is_new, html) {
		$(this.content_id).update(html);
		this.reset();
		Element.scrollTo(this.content_id);		
		if(is_new) dhtmlHistory.add(newLocation);		
	},
	dispatchStateChange: function(url) {
		var newLocation = url.split(/\?/).pop();
		this.stateChange(newLocation, true);
	},		
	grab: function(caching, newLocation, callback) {
		var cached = this.cache.get(newLocation);
		if(cached != undefined)
		{
			if(caching) return;
			callback(cached);
			return;
		}
		if(newLocation == "root") newLocation = "";
		var url = this.url + "?" + newLocation;
		var req = new Ajax.Request(url, {
			method: 'get',
			onCreate: function() {
				if(caching) return;
				$(this.content_id).showLoading({
					message:"Please wait while we load the calendar...", 
					delay: 50,
					style: {
						border: "1px solid #000"						
					}
				});
			}.bind(this),
			onSuccess: function(transport) {				
				var html = transport.responseText;
				if(html.length == 0) 
				{
					if(caching) return;					
					window.location.href = url; // failsafe
					return;
				}
				else
				{
					this.cache.set(newLocation, html);
					if(caching) return;
					if(callback != undefined) callback(html);
					$(this.content_id).hideLoading();
				}
			}.bind(this),
			onFailure: function() {
				if(caching) return;
				window.location.href = url;				
			}.bind(this)
		})
	},
	startCaching: function() {
		return;
		var seconds = 0;
		$$('form.calendar_update input[type="submit"]').each(function(el) {
			el.fire("cache");
//			window.setTimeout(el.fire("cache"), seconds*1000);
//			seconds += 5;
		}, this)
	}
}

