var EventCalendar = Class.create();

EventCalendar.prototype = 
{
    initialize: function(calendar, options) 
    {
		this.calendar = calendar;
		this.eventlist = null;
		this.sa = new SimpleAjax('events', '/event_ajax.php', this.ajaxUpdate.bind(this)) ;
		
		this.container = null;
		this.header = null;
		this.eventDiv = null;
		this.selectedDiv = null;
		
		this.setOptions(options);
		this.calDate = new Date();
		
		this.buildHeader();
		
		//this.selectDay();
		//Event.observe(window, 'resize', this.buildCalendar.bindAsEventListener(this));
	},
	setOptions: function(options) {
      this.options = {
	  	dayWidth: 14.2591, 
	  	dayHeight: 20,
		headerColor: '#FFFFFF',
		dayColor: '#eceadd',
		offDayColor: '#FFFFFF',
		dividerColor: '#dcdcdc',
		selectedDayColor: '#FFFF66',
		days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		daySelectCB: null
	  }
      Object.extend(this.options, options || {});
   },
   selectDay: function(datestamp)
   {
	   if(datestamp == null || datestamp == undefined)
	   {
		   datestamp = this.getDateStamp(this.getMonth(this.calDate), this.calDate.getDate(), this.getYear(this.calDate));
	   }
	   
	   if(this.selectedDiv == null)
	   {
			this.selectedDiv = document.createElement('div');
			this.selectedDiv.style.backgroundColor = this.options.selectedDayColor;
			this.selectedDiv.style.position = 'absolute';
			this.selectedDiv.style.zIndex = 0;
	   }
	   
	   var day = $('date_box_'+datestamp);
	   if(day != null)
	   {
		   var cpos = findPos(this.container);
		   var pos = findPos(day);
		   
		   this.selectedDiv.style.width = day.offsetWidth;
		   this.selectedDiv.style.height = day.offsetHeight;
		   this.selectedDiv.style.top =  pos[1]-cpos[1];
		   this.selectedDiv.style.left = pos[0]-cpos[0];
		   
		   if(this.selectedDiv.parentNode == null)
		   {
			   this.container.appendChild(this.selectedDiv);
		   }
	   }
	   
	   if(this.options.daySelectCB != null)
	   {
		   this.options.daySelectCB(datestamp, this.getEvents(datestamp));
	   }
   },
	getDays: function()
	{
		this.start = new Date();
		this.start.setTime(this.calDate.getTime());
		this.start.setDate(1);
		var day = this.start.getDay();
		this.start.setDate(1-day);
		
		this.end = new Date();
		this.end.setTime(this.calDate.getTime())
		this.end.setDate(15); //set to the middle of next month;
		this.end.setMonth(this.getMonth(this.end));
		this.end.setDate(0);
		day = this.end.getDay();
		this.end.setDate(this.end.getDate()+(6-day));
		
		var endTS = this.end.getTime();
		
		var sDate = new Date();
		sDate.setTime(this.start.getTime());
		var date = sDate.getDate();
		var days = new Array();
		var month = sDate.getMonth();
		while(sDate.getTime() < endTS)
		{
			sDate.setDate(date++);
			if(month != sDate.getMonth())
			{
				date = 2;
				month = sDate.getMonth();
			}
			days[days.length] = {month: this.getMonth(sDate), day: sDate.getDate(), year: this.getYear(sDate)};
		}
		
		return days;
	},
	buildHeader: function()
	{
		if(this.header != null)
		{
			this.calendar.removeChild(this.header);
		}
		
		this.header = document.createElement('div');
		this.header.className = 'ccontainer';
		this.calendar.appendChild(this.header);
		
		var width = this.options.dayWidth;
		for(var i = 0; i < 7; i++)
		{
			var div = document.createElement('div');
			div.className = 'ctitle';
			div.style.top = '0%';
			div.style.left = (i*width)+'%';
			div.style.width = width+'%';
			div.style.backgroundColor = this.options.headerColor;
			div.innerHTML = this.options.days[i];
			this.header.appendChild(div);
		}
	},
	buildCalendar: function()
	{	
		if(this.container != null)
		{
			if(this.selectedDiv != null && this.selectedDiv.parentNode != null)
			{
				this.container.removeChild(this.selectedDiv);
				this.container.removeChild(this.eventDiv);
				this.selectedDiv = null;
				this.eventDiv = null;
				
			}
			this.calendar.removeChild(this.container);
		}
		
		this.container = document.createElement('div');
		this.container.className = 'ccontainer';
		this.container.style.top = '20px';
		this.container.style.height = '100%';
		this.calendar.appendChild(this.container);
		
		var month = this.getMonth(this.calDate);
		var days = this.getDays();
		var rows = days.length/7;
		
		var height = this.calendar.offsetHeight-20;
		this.container.style.height = height;
		height = parseInt(height/rows, 10);
		if(height < this.options.dayHeight) height = this.options.dayHeight;
		
		var width = this.options.dayWidth;		
		var top_pos = 100/rows;
		for(var j = 0; j < rows; j++)
		{
			for(var i = 0; i < 7; i++)
			{
				var index = (j*7)+i;
				var date = days[index];
				
				var div = document.createElement('div');
				div.style.cursor = 'pointer';
				div.style.position = 'absolute';
				div.style.left = (i*width)+'%';
				div.style.width = width+'%';
				div.style.height = height+'px';
				div.style.top = (j*top_pos)+'%';
				div.style.zIndex = 3;
				var datestamp = this.getDateStamp(date.month, date.day, date.year);
				div.id = 'date_box_'+datestamp;
				div.onclick = this.selectDay.bind(this, datestamp);
				var div2 = document.createElement('div');
				div2.className = 'cnumber';
				if(month != date.month)
				{
					div2.style.backgroundColor = this.options.offDayColor;
					div2.style.borderBottom = '0px';
					div2.style.color = '#d1d0cc';
				}
				else
				{
					div2.style.backgroundColor = this.options.dayColor;
				}
				var span = document.createElement('span');
				span.innerHTML = date.day;
				span.style.paddingRight = '5px';
				div2.appendChild(span);
				div.appendChild(div2);
				
				this.container.appendChild(div);
			}
		}
		
		//create dividers
		for(var i = 1; i < 7; i++)
		{
			var div = document.createElement('div');
			div.style.position = 'absolute';
			div.style.left = (i*width)+'%';
			div.style.width = '1px';
			div.style.height = '100%';
			div.style.top = '0%';
			div.style.zIndex = 3;
			div.style.borderLeft = '1px solid '+this.options.dividerColor;
			
			this.container.appendChild(div);
		}
		
		this.eventDiv = document.createElement('div');
		this.eventDiv.className = 'ccontainer';
		this.eventDiv.style.zIndex = 2;
		this.container.appendChild(this.eventDiv);
		this.displayEvents();
		
		$('calendar_month').innerHTML = this.options.months[this.calDate.getMonth()]+' '+ this.getYear(this.calDate);
	},
	nextMonth: function()
	{
		var month = this.calDate.getMonth();
		this.calDate.setMonth(month+1);
		//if we are on the last day of the month and the next month doesn't have the same date
		// we need to set it to the last day of the next month
		if(this.calDate.getMonth() > month+1) 
		{
			this.calDate.setDate(0);
		}
		this.buildCalendar();
	},
	prevMonth: function()
	{
		var month = this.calDate.getMonth();
		this.calDate.setMonth(month-1);
		this.buildCalendar();
	},
	getDateStamp: function(month, day, year, month_only)
	{
		var ds = year.toString();
		if(month < 10)
		{
			ds += '0';
		}
		ds += month.toString();
		
		if(month_only == null || month_only == false)
		{
			if(day < 10)
			{
				ds += '0';
			}
			ds += day.toString();
		}
		else
		{
			ds += '00';
		}
		
		return ds;
	},
	getYear: function(date)
	{
		var year = date.getYear();
		if(year < 1900)
		{
			return 1900+year;
		}
		
		return year;
	},
	getMonth: function(date)
	{
		return date.getMonth()+1;
	},
	requestEvents:function(start, end, refresh)
	{
		this.sa.sendGet(new Array('action=list', 'start_date='+start, 'end_date='+end, 'refresh='+refresh));
	},
	ajaxUpdate:function(response)
	{
		var status = response.getAttribute('status');
		if(status == 'error')
		{
			alert(response.firstChild.nodeValue);
			return false;
		}
		
		var refresh = response.getAttribute('refresh');
		var start = response.getAttribute('start_ds');
		var end = response.getAttribute('end_ds');
		this.addEventList(start, end, util_json(RicoUtil.getContentAsString(response)));
		
		if(refresh == 'true')
		{
			this.displayEvents();
		}
	},
	addEventList: function(startds, endds, edata)
	{
		var events = new Array();
		for(var i = 0; i < edata.length; i++)
		{
			var data = edata[i];
			var date = data.date.split('-');
			events[events.length] = new Event(date[0]+date[1]+date[2], data);
		}
		
		var list = new EventList(startds, endds, events);
		
		var s = this.eventlist;
		if(s == null)
		{
			this.eventlist = list;
		}
		else if(s.start > startds)
		{
			list.next = s;
			s.prev = list;
			this.eventlist = list;
		}
		else
		{
			while(s != null)
			{
				var next = s.next;
				if(next == null)
				{
					s.next = list;
					list.prev = s;
					break;
				}
				else if(endds > s.start && startds < next.start)
				{
					s.next = list;
					list.prev = s;
					list.next = next;
					next.prev = list;
					break;
				}
				
				s = s.next;
			}
		}
	},	
	getEvents: function(datestamp)
	{
		var list = this.eventlist;
		while(list != null)
		{
			if(list.contains(datestamp))
			{
				return list.getEvents(datestamp);
			}
			list = list.next;
		}
		
		return [];
	},
	getEventRange: function(start_ds, end_ds) //only returns first events from first list
	{
		var events = new Array();
		var list = this.eventlist;
		if(list != null)
		{
			var es = list.events;
			for(var i = 0; i < es.length;i++)
			{
				if(es[i].datestamp >= start_ds && es[i].datestamp <= end_ds)
				{
					events.push(es[i]);
				}
			}
		}
		
		return events;
	},
	displayEvents: function()
	{
		var s = parseInt(this.getDateStamp(this.getMonth(this.start), this.start.getDate(), this.getYear(this.start)), 10);
		var e = parseInt(this.getDateStamp(this.getMonth(this.end), this.end.getDate(), this.getYear(this.end)), 10);
		
		if(this.checkRange(s, e) == false)
		{
			return;
		}
		
		var ea = new Array();
		var list = this.eventlist;
		while(list != null)
		{
			if(list.contains(s) || list.contains(e))
			{
				var es = list.getEventRange(s, e);
				for(var i = 0; i < es.length; i++)
				{
					es[i].display(this.eventDiv);
				}
			}
			list = list.next;
		}
		
		return ea;
	},
	checkRange: function(start, end)
	{
		var end_ds = 0, start_ds = 0;
		var foundstart = false, foundend = false;
		var list = this.eventlist;
		while(list != null)
		{
			if(foundstart == false && list.contains(start))
			{
				start_ds = list.end;
				foundstart = true;
			}
			
			if(foundend == false && list.contains(end))
			{
				end_ds = list.start;
				foundend = true;
			}
			
			list = list.next;
		}
		
		if(foundstart == true && foundend == true)
		{
			return true;
		}
		else if(foundstart == false && foundend == false)
		{
			var startDate = new Date();
			startDate.setTime(this.start.getTime());
			var endDate = new Date();
			endDate.setTime(this.end.getTime());
		}
		else if(foundstart == true && foundend == false)
		{
			var startDate = this.datestampToDate(start_ds);
			startDate.setDate(startDate.getDate()+1);
			var endDate = new Date();
			endDate.setTime(this.end.getTime());
		}
		else if(foundstart == false && foundend == true)
		{
			var startDate = new Date();
			startDate.setTime(this.start.getTime());
			var endDate = this.datestampToDate(end_ds);
			endDate.setDate(endDate.getDate()-1);
		}
		
		this.requestEvents(this.getYear(startDate)+'-'+this.getMonth(startDate)+'-'+startDate.getDate(),
								this.getYear(endDate)+'-'+this.getMonth(endDate)+'-'+endDate.getDate(), true);
			
		return false;
	},
	datestampToDate: function(ds)
	{
		var m = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
		ds = ds.toString();
		var month = parseInt(ds.substring(4, 6), 10);
		var day = parseInt(ds.substring(6,8), 10);
		var year = parseInt(ds.substring(0,4));
		
		return new Date(m[month]+' '+day+', '+year+' 00:00:00');
	}
}

var EventList = Class.create();

EventList.prototype =
{
    initialize: function(start, end, events) 
    {
		this.start = start;
		this.end = end;
		
		this.events = events;
		this.next = null;
		this.prev = null;
	},
	contains: function(datestamp)
	{
		return (this.start <= datestamp && this.end >= datestamp); 
	},
	getEvents: function(datestamp)
	{
		var es = new Array();
		for(var i  = 0; i < this.events.length; i++)
		{
			if(this.events[i].datestamp == datestamp)
			{
				es[es.length] = this.events[i];
			}
		}
		return es;
	},
	getEventRange: function(start, end)
	{
		var es = new Array();
		for(var i  = 0; i < this.events.length; i++)
		{
			var event = this.events[i]; 
			if(event.datestamp >= start && event.datestamp <= end)
			{
				es[es.length] = event;
			}
		}
		return es;
	}
}

var Event = Class.create();
Event.prototype =
{
    initialize: function(datestamp, data) 
    {
		this.datestamp = datestamp;
		this.data = data;
		
		this.top = 0;
		this.left = 0;
		this.div = null;
	},
	build: function(parent)
	{
		var cpos = findPos(parent);
		var day = $('date_box_'+this.datestamp);
		var pos = findPos(day);
		
		this.top = pos[1]-cpos[1]+15;
		this.left = pos[0]-cpos[0]+2;
		
		this.div = document.createElement('div');
		this.div.className = 'cevent';
		this.div.style.width = day.offsetWidth-4;
		this.div.style.backgroundColor = '#db9f00';
		this.div.style.top = this.top;
		this.div.style.left = this.left;
		
		var divt = document.createElement('div');
		divt.className = 'cevent_text';
		divt.innerHTML = '&nbsp;';
		divt.style.width = day.offsetWidth-4;
		this.div.appendChild(divt);
		
		Rico.Corner.round(this.div, {compact: true});
	},
	display: function(parent)
	{
		if(this.div != null && this.div.parentNode != null)
		{
			this.div.parentNode.removeChild(this.div);
		}
		this.build(parent);		
		parent.appendChild(this.div);
	},
	hide: function()
	{
		this.parent.removeChild(this.div);
	},
	getDateTime: function()
	{
		var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
		var parts = this.data.date.split('-');
		var time = this.data.start.split(':');
		var mer = 'AM';
		var hour = parseInt(time[0]);
		if(hour > 12)
		{
			hour -= 12;
			mer = 'PM';
		}
		else if(hour == 12)
		{
			mer = 'PM';
		}
		else if(hour == 0)
		{
			hour = 12;
		}
		
		return months[parts[1]-1]+' '+parseInt(parts[2], 10)+', '+parts[0]+' '+hour+':'+time[1]+' '+mer+' MST';
	}
}
