var Calendar = new Class({
	
	Implements:[Options, Events],
	options:{
		urlGetCalendar		: "getcalendar",
		urlSetDates			: "public/datescontroller/setdates",
		startDateProperty	: "startDate",
		endDateProperty		: "endDate"
	},
	
	calendarGenerator	: undefined,
	dayCollection		: undefined,
	selections			: undefined,
	rangeSelector 		: undefined,
	
	baseUrl				: undefined,
	
	initialize:	function(calendarObject, options)
	{
		this.setOptions(options);
		this.setUp();
		this.createCalendar(calendarObject);
	},
	
	setUp: function()
	{
		this.baseUrl = document.controllerUrl;
		
		this.calendarGenerator	= new CalendarGenerator();
		this.calendarGenerator.addEvent("onDayGeneration", this.addElementToCollection.bind(this));
		
		this.dayCollection		= new DayCollection();
		
		this.selections			= new CalendarSelections(this.dayCollection);
		
		this.searchBus = new SearchBus();
		this.searchBus.registerCallback(this.addDayClass.bind(this)		, "dayHover");
		this.searchBus.registerCallback(this.removeDayClass.bind(this)	, "dayOut");
		
		this.searchBus.registerCallback(this.rangeSelection.bind(this)	, "rangeSelection");
	
		this.selections.addEvent("onDaySelectionHover"	, this.onSelectionHover.bind(this))
		this.selections.addEvent("onCreateRange"		, this.onRangeSelected.bind(this))
		this.selections.addEvent("onMouseEnter"			, this.dayCellMouseEnter.bind(this));
		this.selections.addEvent("onMouseLeave"			, this.dayCellMouseLeave.bind(this));
		this.selections.addEvent("onRangeSeted"			, this.onRangeSeted.bind(this));
		this.selections.addEvent("onInitSelection"		, this.onInitSelection.bind(this));

	}, 
	
	/** Calendar GENERATION **/
	createCalendar: function(calendarObject)
	{
		this.dayCollection.reset();
		this.calendarGenerator.generateCalendar(calendarObject);
		this.selections.reset();
	},
	
	addElementToCollection: function(timestamp, element, dayObject)
	{
		this.dayCollection.addDomElement(timestamp, element, dayObject.weekDay);
		
		if(!$defined(dayObject.params.blocked))
		{
			this.dayCollection.addClass(timestamp, "selectable");
		}
		else
		{
			this.dayCollection.addClass(timestamp, "unSelectable");
		}
		
	},
	/*****/
	
	
	unselectAll: function()
	{
		if(!this.selections.hover)
		{
			return false;
		}
		
		var range = this.getCurrentRange();
		
		if(range[this.options.startDateProperty] == undefined)
		{
			return false;
		}
		
		this.dayCollection.performOnRange(range[this.options.startDateProperty], range[this.options.endDateProperty], this.dayCollection.unHighlight.bind(this.dayCollection));
		
		this.searchBus.trigger("calendarUnselectAll", range);
		
		var fullRange = this.dayCollection.getRange(range[this.options.startDateProperty], range[this.options.endDateProperty]);
		fullRange.each(function(day){
			this.searchBus.trigger("dayUnSelection", day.getTimestamp());
		}.bind(this));
	},
	
	stopEvent: function(e)
	{
		e.stop();
	},
	
	rangeSelection: function(range)
	{
		var range = this.dayCollection.getRange(range[this.options.startDateProperty], range[this.options.endDateProperty]);
		
		range.each(function(day){
			this.searchBus.trigger("daySelection", day.getTimestamp());
		}.bind(this));
	},
	
	addDayClass: function(params)
	{
		this.dayCollection.addClass(params.timestamp, params.cssClass);
	},
	
	removeDayClass: function(params)
	{
		this.dayCollection.removeClass(params.timestamp, params.cssClass);
	},
	
	getCurrentRangeSelected: function()
	{	
		return this.getRangeObject(this.rangeSelector.range.start.getTime()/1000, this.rangeSelector.range.end.getTime()/1000)
	},
	
	getCurrentRange: function()
	{
		return this.getRangeObject(this.initTimestamp, this.endTimestamp);
	},
	
	getRangeObject: function(initTimestamp, endTimestamp)
	{
		var range 		= {};
		
		if(initTimestamp > endTimestamp)
		{
			var auxTimestamp =  initTimestamp;
			initTimestamp = endTimestamp;
			endTimestamp = auxTimestamp;
		}
		
		range[this.options.startDateProperty] 	= initTimestamp;
		range[this.options.endDateProperty]	= endTimestamp;
		return range;
	},
	
	/** REQUESTS **/
	requestNewCalendarRange: function()
	{
		var data 			= this.getCurrentRangeSelected();
		data["apartmentId"] = this.apartmentId;
		
		this.request(this.baseUrl+this.options.urlGetCalendar, data);
	},
	/****/
	
	
	//
	request: function(url, data, onCompleteFunctions)
	{
		this.ajaxRequest = new Request.JSON({url:url, data:{"QUERY":JSON.encode(data)}, onComplete:this.requestComplete.bindWithEvent(this, [onCompleteFunctions])});
		this.ajaxRequest.send();
	},
	
	requestComplete: function(response, onCompleteFunctions)
	{
		if($defined(response.ANSWER) && response.ANSWER.result == false)
		{
			this.unselectAll();
		}
	},
	
	executeArrayFunctions: function(functions)
	{
		if(!$defined(functions)) 
		{
			return false;
		}
		
		functions.each(function(func){
			func();
		});
	},
	
	
	/** Selection EVENTS **/
	onSelectionHover: function(timestamp)
	{
		
	},
	
	onRangeSelected: function(initTimestamp, endTimestamp, event, daysNum)
	{
		this.initTimestamp 	= initTimestamp;
		this.endTimestamp	= endTimestamp;
		
		if(initTimestamp > endTimestamp)
		{
			this.initTimestamp 	= endTimestamp;
			this.endTimestamp	= initTimestamp;
		}
		
		var url = this.options.urlSetDates;
		
		var data = this.getRangeObject(initTimestamp, endTimestamp);
		this.dayCollection.addClass(endTimestamp, "loading");
		
		this.request(url, data);
		this.searchBus.trigger("rangeSelection", data);
	},
	
	onInitSelection: function(timestamp)
	{
		this.unselectAll();
		this.searchBus.trigger("calendarFirstDateSelected", timestamp);
	},
	
	onRangeSeted: function(initTimestamp, endTimestamp)
	{
		this.initTimestamp 	= initTimestamp;
		this.endTimestamp	= endTimestamp; 
		var data = this.getRangeObject(initTimestamp, endTimestamp);
		this.searchBus.trigger("rangeSelection", data);
	},
	

	
	dayCellMouseEnter: function(event, dayCell, index)
	{
		var timestamp = dayCell.get("alt");
		this.searchBus.trigger("dayHover", {timestamp:timestamp, cssClass:"highlighted"});
	},
	
	dayCellMouseLeave: function(event, dayCell, index)
	{
		var timestamp = dayCell.get("alt");
		this.searchBus.trigger("dayOut", {timestamp:timestamp, cssClass:"highlighted"});
	}
		
	/****/
	
});