/*
Version 10.02.09
Version 10.02.11
	- Removed the need to manually call CalendarSet.setTheme('default')
Version 10.02.22
	- Fixed positioning of date picker
Version 10.04.07
	- Added EventList object
	- Changed Event.timestamp to Event.start_time and Event.end_time
	- Changed full view to look nicer
Version 10.04.09
	- added the detail popup
	- created your mom
	- added the details array to hold details to display in the detail window
Version 10.05.03
	- Fixed onclick n00b h4x
Version 10.06.01
	- Made the picker disappear when the input it's attached to gets blurred
Version 10.10.29
	- Bug fixes to the date/time displaying functions
	- Added the Time object
	- Fixed selected date not highlighting on date picker
Version 10.11.09
	- Added href to event details
*/

var CalendarSet=
{
	_theme_set: false,
	_picker:
	{
		calendar: null,
		input: null,
		onclick: null,
		ready_to_remove: true
	},
	
	pickDate: function(input, onclick)
	{
		if(!!this._picker.input)
			this._picker.input.parentNode.removeChild(this._picker.calendar.div);
		
		if(!!input && this._picker.input!=input)
		{
			this._picker.input=input;
			this._picker.onclick=onclick;
			this._picker.calendar=new this._Calendar
			({
				css_class: 'picker',
				append_after: true,
				compact: true,
				start_date: input.value,
				onclick:function(date)
				{
					CalendarSet._picker.input.value=(date.getMonth()+1)+'/'+date.getDate()+'/'+date.getFullYear();
					
					if(!!CalendarSet._picker.onclick)
						(CalendarSet._picker.onclick.partial(date).bind(this))();
					
					CalendarSet.pickDate();
				}
			});
			if(this._picker.input.value!='')
			{
				this._picker.calendar.events.add({
					start_date: CalendarSet.stringToDate(this._picker.input.value),
					end_date: CalendarSet.stringToDate(this._picker.input.value)
				});
			}
			this._picker.calendar.write(input);
			
			addEvent(this._picker.calendar.div, 'mousedown', function()
			{
				this._picker.ready_to_remove = false;
			}.bind(this));
			addEvent(this._picker.calendar.div, 'mouseup', function()
			{
				this._picker.ready_to_remove = true;
			}.bind(this));
			
			addEvent(this._picker.input, 'blur', function()
			{
				if(this._picker.ready_to_remove)
					CalendarSet.pickDate();
			}.bind(this));
		}
		else
		{
			this._picker.calendar=null;
			this._picker.input=null;
			this._picker.onclick=null;
			this._picker.ready_to_remove=true;
		}
	},
	
	_Calendar: function(options)
	{
		this.css_class=options.css_class;
		this.append_after=options.append_after;
		this.compact=options.compact;
		this.onclick=options.onclick;
		this.ondayclick = options.ondayclick;
		
		if(!!options.event_href)
			this.event_href=options.event_href;
		if(!!options.event_onclick)
			this.event_onclick=options.event_onclick;
			
		if(!!options.start_date)
		{
			if(typeof(options.start_date)=='object')
				this.date_shown=options.start_date;
			else if(typeof(options.start_date)=='string')
				this.date_shown=CalendarSet.stringToDate(options.start_date);
		}
		else
			this.date_shown=new Date();
		this.date_shown.setDate(1);
		
		this.container_element=null;
		if(!!options.events && options.events instanceof CalendarSet.EventList)
			this.events=options.events;
		else
			this.events=new CalendarSet.EventList();
		
		this.fade = false;
		if(!!options.fade)
			this.fade = options.fade;
		
		if(!CalendarSet._theme_set)
			CalendarSet.setTheme('default');
	},
	
	Full: function(options)
	{
		if(!options)
			options={};
		options.css_class='full';
		options.compact=false;
		options.append_after=false;
		return (new CalendarSet._Calendar(options));
	},
	
	Mini: function(options)
	{
		if(!options)
			options={};
		options.css_class='mini';
		options.compact=true;
		options.append_after=false;
		return (new CalendarSet._Calendar(options));
	},
	
	EventList: function(events)
	{
		var i;
		
		this._events = [];
		this.length = 0;
		if(!!events)
		{
			for(i=0; i<events.length; i++)
				this.add(events[i]);
		}
	},
	
	Event: function(options)
	{
		if(typeof(options.start_date)=='object')
			this.start_date=options.start_date;
		else
		{
			options.start_date=parseInt(options.start_date);
			if(options.start_date<10000000000) // Timestamp is apparently in seconds; Javascript needs milliseconds
				options.start_date*=1000;
			this.start_date=new Date(options.start_date);
		}
		
		if(typeof(options.end_date)=='object')
			this.end_date=options.end_date;
		else
		{
			options.end_date=parseInt(options.end_date);
			if(options.end_date<10000000000) // Timestamp must be in seconds; Javascript needs milliseconds
				options.end_date*=1000;
			this.end_date=new Date(options.end_date);
		}
		
		this.start_time=null;
		if(options.start_time!=null)
			this.start_time=new CalendarSet.Time(options.start_time);
		
		this.end_time=null;
		if(options.end_time!=null)
			this.end_time=new CalendarSet.Time(options.end_time);
		
		if(!!options.onclick)
			this.onclick = options.onclick;
		
		if(!!options.title)
			this.title=options.title;
		if(!!options.description)
			this.description=options.description;
		
		this._interval = null;
		
		this.details = [];
		if(!!options.details)
			this.details=options.details;
	},
	
	Time: function(time)
	{
		this.hours=0;
		this.minutes=0;
		this.seconds=0;
		
		if(typeof(time)!='object')
		{
			if(time >= 3600)
			{
				this.hours = Math.floor(time/3600);
				time = (time % 3600);
			}
			if(time >= 60)
			{
				this.minutes = Math.floor(time/60);
				time = (time % 60);
			}
			
			this.seconds = Math.floor(time);
		}
		else
		{
			this.hours=time.hours;
			this.minutes=time.minutes;
			this.seconds=time.seconds;
		}
	},
	
	setTheme: function(theme)
	{
		var fileref;
		
		fileref=document.createElement('link');
		fileref.setAttribute('rel', 'stylesheet');
		fileref.setAttribute('type', 'text/css');
		fileref.setAttribute('href', '/themes/CalendarSet/'+theme+'/theme.css');
		fileref.setAttribute('media', 'screen');
		document.getElementsByTagName('head')[0].appendChild(fileref);
		
		fileref=document.createElement('link');
		fileref.setAttribute('rel', 'stylesheet');
		fileref.setAttribute('type', 'text/css');
		fileref.setAttribute('href', '/themes/CalendarSet/'+theme+'/print.css');
		fileref.setAttribute('media', 'print');
		document.getElementsByTagName('head')[0].appendChild(fileref);
		
		this._theme_set=true;
		return this;
	},
	
	stringToDate: function(string)
	{
		var parts;
		
		parts=string.split(/[\/\-\.]/);
		return new Date(parts[2], parts[0]-1, parts[1], 0, 0, 0);
	}
};

CalendarSet._Calendar.prototype.write=function(element)
{
	var div, table, tbody, tr, td, row, col, i, days_in_month, display_date, weeks_in_month, today;
	var day_event_list, head_div, event_ul, event_li, after_15 = false, display_up = false;
	
	if(!!element)
		this._element=element;
	
	div=document.createElement('div');
	div.className='CalendarSet CalendarSet_'+this.css_class;
	table=document.createElement('table');
	div.appendChild(table);
	tbody=document.createElement('tbody');
	table.appendChild(tbody);
	
	tr=document.createElement('tr');
	td=document.createElement('td');
	td.className='jump_month';
	td.onclick=function()
	{
		this.jumpMonths(-1).write();
	}.bind(this);
	td.appendChild(document.createTextNode('<'));
	tr.appendChild(td);
	td=document.createElement('td');
	td.className='month';
	td.setAttribute('colSpan', '5');
	if(this.compact)
		td.appendChild(document.createTextNode(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][this.date_shown.getMonth()] +' '+ this.date_shown.getFullYear()));
	else
		td.appendChild(document.createTextNode(['January','Febuary','March','April','May','June','July','August','September','October','November','December'][this.date_shown.getMonth()] +' '+ this.date_shown.getFullYear()));
	tr.appendChild(td);
	td=document.createElement('td');
	td.className='jump_month';
	td.onclick=function()
	{
		this.jumpMonths(1).write();
	}.bind(this);
	td.appendChild(document.createTextNode('>'));
	tr.appendChild(td);
	tbody.appendChild(tr);
	
	tr=document.createElement('tr');
	for(col=0; col<7; col++)
	{
		td=document.createElement('td');
		td.className='weekday';
		if(this.compact)
			td.appendChild(document.createTextNode(['S','M','T','W','T','F','S'][col]));
		else
			td.appendChild(document.createTextNode(['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][col]));
		tr.appendChild(td);
	}
	tbody.appendChild(tr);
	
	days_in_month=[31,28+(this.date_shown.getFullYear()%4==0? 1 : 0),31,30,31,30,31,31,30,31,30,31][this.date_shown.getMonth()];
	display_date=new Date(this.date_shown.getTime());
	display_date.setDate(1);
	weeks_in_month=Math.ceil((display_date.getDay() + days_in_month) / 7);
	today=new Date();
	for(row=0; row<weeks_in_month; row++)
	{
		tr=document.createElement('tr');
		for(col=0; col<7; col++)
		{
			td=document.createElement('td');
			td.className='day';
			if(!((row==0 && col<display_date.getDay()) || (row==weeks_in_month-1 && display_date.getMonth()!=this.date_shown.getMonth())))
			{
				if(!!this.onclick)
				{
					td.onclick=this.onclick.partial(new Date(display_date)).bind(this);
					td.className+=' clickable';
				}
				
				if(display_date.getDate()>15)
					after_15 = true;
				
				if(after_15 && display_date.getDay()==0)
					display_up = true;
				
				head_div = document.createElement('div');
				head_div.className = 'day_header';
				head_div.appendChild(document.createTextNode(display_date.getDate()));
				td.appendChild(head_div);
				if(display_date.getDate()==today.getDate() && display_date.getMonth()==today.getMonth() && display_date.getFullYear()==today.getFullYear())
					td.className+=' today';
				
				day_event_list = new CalendarSet.EventList();
				event_ul = document.createElement('ul');
				event_ul.className = 'event_list';
				for(i=0; i<this.events.length; i++)
				{
					if(display_date.getDate()>=this.events.get(i).start_date.getDate() && display_date.getMonth()>=this.events.get(i).start_date.getMonth() && display_date.getFullYear()>=this.events.get(i).start_date.getFullYear() && display_date.getDate()<=this.events.get(i).end_date.getDate() && display_date.getMonth()<=this.events.get(i).end_date.getMonth() && display_date.getFullYear()<=this.events.get(i).end_date.getFullYear())
					{
						day_event_list.add(this.events.get(i));
						if(!this.compact)
						{
							event_li = document.createElement('li');
							event_li.innerHTML = this.events.get(i).title;
							
							event_li.onmouseover = this.events.get(i).showDetails.partial(event_li, display_date.getDay()>=4, display_up).bind(this.events.get(i));
							
							if(!!this.events.get(i).onclick)
							{
								if(typeof(this.events.get(i).onclick)=='function')
									event_li.onclick = this.events.get(i).onclick;
								else
									event_li.onclick = new Function(this.events.get(i).onclick);
							}
							
							event_ul.appendChild(event_li);
						}
						if(!!this.events.get(i).href)
						{
							td.className+=' clickable';
							td.onclick=function(href)
							{
								location.href=href;
							}.partial(this.event_href);
						}
					}					
				}
				
				
				if(day_event_list.length>0)
				{
					if(!!this.ondayclick)
					{
						if(typeof(this.ondayclick)=='function')
							td.onclick = this.ondayclick.partial((display_date.getMonth()+1)+'/'+display_date.getDate()+'/'+display_date.getFullYear());
						else
							td.onclick = new Function((display_date.getMonth()+1)+'/'+display_date.getDay()+'/'+display_date.getFullYear(), this.ondayclick);
					}
					
					td.appendChild(event_ul);
					td.className+=' selected';
				}
				display_date.setDate(display_date.getDate()+1);
			}
			tr.appendChild(td);
		}
		tbody.appendChild(tr);
	}
	
	if(this.append_after)
	{
		var x, y, parent;
		
		x=this._element.offsetLeft;
  		y=this._element.offsetTop+this._element.scrollTop+this._element.scrollHeight;
		parent=this._element;
		while(parent.offsetParent)
		{
			parent=parent.offsetParent;
			x+=parent.offsetLeft;
			y+=parent.offsetTop;
		}
		
		if(this.div)
			this._element.parentNode.removeChild(this.div);
		this.div=this._element.parentNode.insertBefore(div, this._element.nextSibling);
		this.div.style.top=y+'px';
		this.div.style.left=x+'px';
	}
	else
	{
		while(this._element.childNodes.length > 0)
			this._element.removeChild(this._element.childNodes[0]);
		this.div=this._element.appendChild(div);
	}
	return this;
}

CalendarSet._Calendar.prototype.jumpMonths=function(months)
{
	this.date_shown.setMonth(this.date_shown.getMonth()+months);
	return this;
}

CalendarSet.EventList.prototype.add = function(event)
{
	if(event instanceof CalendarSet.Event)
		this._events.push(event);
	else
		this._events.push(new CalendarSet.Event(event));
	this.length++;
	return this;
}

CalendarSet.EventList.prototype.remove = function(i)
{
	this._events.splice(i, 1);
	this.length--;
	return this;
}

CalendarSet.EventList.prototype.get = function(i)
{
	return this._events[i];
}

CalendarSet.Event.prototype.dateText = function(include_date)
{
	var str='';
	
	if(include_date!==false)
		include_date = true;
	
	if(include_date || this.start_date.getTime()!=this.end_date.getTime())
		str += php_date('n/j/Y', this.start_date);
	if(this.start_date.getTime()==this.end_date.getTime() && this.start_time==null && this.end_time==null)
		str += ' all day';
	else if((this.start_time!=null && this.end_time!=null) && ((this.start_date.getTime()==this.end_date.getTime() && this.start_time.getTime()!=this.end_time.getTime()) || (this.start_date.getTime()!=this.end_date.getTime() && this.start_time.getTime()!=this.end_time.getTime())))
		str += ' '+this.start_time;
	else if(this.start_time!=null)
		str += this.start_time;
	
	if(this.start_date.getTime()!=this.end_date.getTime() || (this.start_time!=null && this.end_time!=null && this.start_time.getTime()!=this.end_time.getTime()))
	{
		str += ' to ';
		if(this.end_time!=null)
			str += this.end_time;
		
		if(this.start_date.getTime()!=this.end_date.getTime())
			str += php_date('n/j/Y', this.end_date);
	}
	return str;
}

CalendarSet.Event.prototype.showDetails = function(li, to_left, display_up, fade)
{
	var x, y, width, height, parent, div, divs, i, tmp_div, tmp_span, tmp_a;
	
	divs = document.getElementsByClassName('CalendarSet_detail_window');
	for(i=0; i<divs.length; i++)
		divs[i].parentNode.removeChild(divs[i]);
	
	
	div = document.createElement('div');
	div.className = 'CalendarSet_detail_window';
	div.style.opacity = 0;
	document.body.appendChild(div);
	
	tmp_div = document.createElement('div');
	tmp_div.className = 'event_header';
	tmp_div.innerHTML = this.title;
	div.appendChild(tmp_div);
	
	tmp_div = document.createElement('div');
	tmp_div.className = 'detail_time';
	tmp_div.appendChild(document.createTextNode(this.dateText(false)));
	div.appendChild(tmp_div);
	
	for(i=0; i<this.details.length; i++)
	{
		tmp_div = document.createElement('div');
		tmp_div.className = 'detail';
		if(!!this.details[i].className)
			tmp_div.className += ' '+this.details[i].className;
		tmp_span = document.createElement('span');
		tmp_span.className = 'detail_name';
		tmp_span.innerHTML = !!this.details[i].name?this.details[i].name+': ':'';
		tmp_div.appendChild(tmp_span);
		
		tmp_span = document.createElement('span');
		tmp_span.className = 'detail_value';
		tmp_span.innerHTML = this.details[i].value;
		if(!!this.details[i].href)
		{
			tmp_a=document.createElement('a');
			tmp_a.href=this.details[i].href;
			tmp_a.appendChild(tmp_span);
			tmp_div.appendChild(tmp_a);
		}
		else
			tmp_div.appendChild(tmp_span);
		
		div.appendChild(tmp_div);
	}
	
	li.onmouseout = this.hideDetails.partial(div, fade, 500).bind(this);
	div.onmouseover = function(){clearTimeout(this._timeout)}.bind(this);
	div.onmouseout = this.hideDetails.partial(div, fade, 500).bind(this);
	
	x=li.offsetLeft;
	y=li.offsetTop;
	parent=li;
	while(parent.offsetParent)
	{
		parent=parent.offsetParent;
		x+=parent.offsetLeft;
		y+=parent.offsetTop;
	}
	width = li.clientWidth;
	height = li.clientHeight;
	
	if(display_up)
	{
		div.style.top = (y-div.clientHeight-3)+'px';
		if(to_left)
			div.style.left = (x-(div.clientWidth - width))+'px';
		else
			div.style.left = (x)+'px';
	}
	else
	{
		div.style.top = (y)+'px';
		if(to_left)
			div.style.left = (x-div.clientWidth)+'px';
		else
			div.style.left = (width+x)+'px';
	}
	
	if(fade)
	{
		this._interval = setInterval
		(function(div)
		{
			div.style.opacity=parseFloat(div.style.opacity)+(.1);
			if(div.style.opacity==1)
				clearInterval(this._interval);
				
		}.partial(div).bind(this), 25);
	}
	else
		div.style.opacity = 1;
}

CalendarSet.Event.prototype.hideDetails = function(div, fade, delay)
{
	if(fade)
	{
		this._timeout = setTimeout(function()
		{
			clearInterval(this._interval);
			this._interval = setInterval(
			function(div)
			{
				div.style.opacity=parseFloat(div.style.opacity)-(.1);
				if(div.style.opacity==0)
				{
					clearInterval(this._interval);
					div.parentNode.removeChild(div);
				}
			}.partial(div).bind(this), 25);
		}.partial(div).bind(this), delay);
	}
	else
	{
		this._timeout = setTimeout(function(){if(!!div.parentNode) div.parentNode.removeChild(div)}.partial(div), delay);
	}
}

CalendarSet.Time.prototype.getTime=function()
{
	return (this.hours*3600 + this.minutes*60 + this.seconds)*1000;
}

CalendarSet.Time.prototype.toString=function()
{
	return ((this.hours+11) % 12 + 1) +':'+ (this.minutes<10?'0'+this.minutes:this.minutes)+' '+(this.hours>=12?'pm':'am');
}

