var DayCollection = new Class({
	
	/*CONSTS*/
	END_OF_COLLECTION: "END_OF_COLLECTION",
	//
	
	firstDay	:undefined,
	lastDay		:undefined,
	
	pointer		:false,
	days		:{},
	
	weekDays	:{
		1 : {},
		2 : {},
		3 : {},
		4 : {},
		5 : {},
		6 : {},
		7 : {}
	},
	
	initialize: function(days)
	{
		if($defined(days))
		{
			this.setCollection(days);
		}
	},
	
	reset: function()
	{
		this.pointer 	= false;
		this.days 		= {};
		this.weekDays	= {1 : {}, 2 : {}, 3 : {}, 4 : {}, 5 : {}, 6 : {}, 7 : {}};
	},
	
	setCollection: function(days)
	{
		this.reset();
		days.each(this.push.bind(this));
	},
	
	push: function(day)
	{
		
		if(!$defined(day.OBJECT_TYPE) || day.OBJECT_TYPE != "DAY") 
		{
			throw "Day needs to be days objects";
		}
		
		var isFirstDay = ($H(this.days).getLength() == 0);
		
		if(isFirstDay) 
		{
			this.firstDay = day;
			day.setPrevious(false);
		}
		else
		{
			this.lastDay.setNext(day);
			day.setPrevious(this.lastDay);
			day.setNext(this.END_OF_COLLECTION)
		}
		
		this.lastDay = day;
		this.days[day.getTimestamp()] = day;
		if($defined(day.getWeekNum()))
		{
			this.weekDays[day.getWeekNum()][day.getTimestamp()] = day;
		}
	},
	
	addDomElement: function(timestamp, element, weekDayNum)
	{
		if(!$defined(this.days[timestamp]))
		{
			var day = new Day(timestamp, element, weekDayNum);
			this.push(day);
		}
		else
		{
			this.days[timestamp].addDomElement(element);
		}
	},
	
	getFirst: function()
	{
		return this.firstDay;
	},
	
	getLast: function()
	{
		return this.lastDay;
	},
	
	setPointer: function(timestamp)
	{
		this.pointer = this.days[timestamp];
	},
	
	getNext: function()
	{
		if(this.pointer === false)
		{
			this.pointer = this.getFirst();
			return this.pointer;
		}
		
		if(this.pointer.getNext() == this.END_OF_COLLECTION)
		{
			this.pointer = this.END_OF_COLLECTION;
		}
		else
		{
			this.pointer = this.pointer.getNext();
		}
		
		return this.pointer;
	},
	
	getPrevious: function()
	{
		if(this.pointer === false) 
		{
			return this.pointer;
		}
		
		if(this.pointer == this.END_OF_COLLECTION)
		{
			this.pointer = this.getLast();
		}
		else
		{
			this.pointer = this.pointer.getPrevious();
		}
		
		return this.pointer;
	},
	
	getDay: function(timestamp)
	{
		return this.days[timestamp];
	},
	
	addClass: function(timestamp, cssClass)
	{
		this.days[timestamp].addClass(cssClass);
	},
	
	removeClass: function(timestamp, cssClass)
	{
		if($defined(this.days[timestamp]))
		{
			this.days[timestamp].removeClass(cssClass);
		}
	},
	
	highlight: function(timestamp)
	{
		this.days[timestamp].highlight();
	},
	
	unHighlight: function(timestamp)
	{
		if(!$defined(this.days[timestamp]))
		{
			return false;
		}
		
		this.days[timestamp].unHighlight();
	},
	
	highlightSpecificRangeDays: function(weekDay)
	{
		$H(this.weekDays[weekDay]).each(function(day, timestamp){
			this.highlight(timestamp)
		}.bind(this))
	},
	
	unHighlightSpecificRangeDays: function(weekDay)
	{
		$H(this.weekDays[weekDay]).each(function(day, timestamp){
			this.unHighlight(timestamp)
		}.bind(this))
	},
	
	highlightRange: function(initTimestamp, endTimestamp)
	{
		this.performOnRange(initTimestamp, endTimestamp, this.highlight.bind(this));
	},
	
	unHighlightRange: function(initTimestamp, endTimestamp)
	{
		this.performOnRange(initTimestamp, endTimestamp, this.unHighlight.bind(this));
	},
	
	performOnRange: function(initTimestamp, endTimestamp, action)
	{
		action(initTimestamp);
		if(initTimestamp == endTimestamp)
		{
			return;
		}
		
		this.setPointer(initTimestamp);
		var direction = this.getNext.bind(this);
		
		if(initTimestamp > endTimestamp)
		{
			var direction = this.getPrevious.bind(this);
		}
		
		while(day = direction())
		{
			action(day.getTimestamp());
			if(day.getTimestamp() == endTimestamp)
			{
				break;
			}
		}
	},
	
	getRange: function(initTimestamp, endTimestamp)
	{
		var range = [];
		var init 	= initTimestamp;
		var end 	= endTimestamp;
		
		if(init == end)
		{
			range.push(this.getDay(init));
			return range;
		}
		
		if(initTimestamp > endTimestamp)
		{
			init = endTimestamp;
			end = initTimestamp;
		}
		
		
		this.setPointer(init);
		range.push(this.getDay(init));
		
		while(day = this.getNext())
		{
			range.push(day);
			if(day.getTimestamp() >= end)
			{
				break;
			}
			
		}
		
		return range;
	}
	
});