//=================================================================================================
//	TCalendar 
//-------------------------------------------------------------------------------------------------
//	PROPERTIES 
//		beginDate	Date				The begindate of the calendar (calculated)
//		calDiv		String			The ID of the DIV which will contain the calendar.
//		count			int				The number of items.
//		date			Date				The selected date.
//		dateDiv		String			The ID of the DIV which will contain the current selected date.
//		endDate		Date				The enddate of the calendar (calculated)
//		items[]		TCalendarItem	Array of TCalendarItems. The agenda-items.
//		mainDiv		String			The ID of the DIV which will contain the rendered items.
//		name			String			The name of the class.
//		template		String			The XSL to render an item.
//		type			TCalendarType	The filter for the calendar.
//	
//	METHODS 
//		setType		void				param: type.
//		getDate		String			The date displayed in "dateDiv".
//		setDate		void				param: date, sets the date and refreshes the calendar.
//		add			TCalendarItem	params: ID, title, teaser, beginDate, endDate. Creates a new 
//											TCalendarItem and adds it to the list.
//		prior			void				Go to the prior period (Depends on the type of the calendar).
//		next			void				Go to the next period.
//		refresh		void				Recalcs the begin- and enddate and calls redraw()
//		redraw		void				Redraws the calendar.
//		write			void				Join the XML and XSL and fill mainDiv.
//		createXML	String			Create the XML for the calendar. Calls "createXML" for each 
//											TCalendarItem.
//	EVENTS 
//		onChange		function			Triggers when a user selects another date(range) on the calendar. 
//											Params "sender" and "count" (the number of items visible).
//=================================================================================================
//	TCalendarItem 
//-------------------------------------------------------------------------------------------------
//	PROPERTIES 
//		owner			TCalendar		The owner and creator of "this".
//		ID				int				The itmID of the item.
//		title			String			The itmName of the item.
//		teaser		String			The itmTeaser of the item.
//		thumb			String			The thumbnail image of the item
//		beginDate	Date				The begindate of the item.
//		endDate		Date				The enddate of the item.
//	METHODS 
//		getShow		bool				Whether the item will be shown based on the dates of the item and 
//											calendar.
//		getDisplay	String			Base on getShow() returns style="display:none" or an empty string.
//		formatDate	String			How the dates-/times will be displayed.
//		createXML	String			Creates the XML for this item.
//=================================================================================================
//	enum TCalendarType ( ctDay, ctWeek, ctMonth, ctCustom );
//-------------------------------------------------------------------------------------------------
var
	TCalendarType = new Array("ctDay", "ctWeek", "ctMonth", "ctCustom"), 
	ctDay         = 0, 
	ctWeek        = 1, 
	ctMonth       = 2, 
	ctCustom      = 4;
//=================================================================================================
function replacePar( value )
{
	value = value.replace( /\(/g, "\\(");
	value = value.replace( /\)/g, "\\)");
	
	return value
}
//=================================================================================================
TCalendar = function( name, dateDiv, mainDiv, calDiv, type, date, beginDate, endDate )
{
	this.className = "TCalendar";
	this.beginDate = new Date( beginDate );
	this.calDiv    = calDiv;
	this.count     = 0;
	this.date      = new Date( date );
	this.dateDiv   = dateDiv;
	this.dates     = new Array();
	this.endDate   = new Date( endDate );
	this.items     = new Array();
	this.mainDiv   = mainDiv;
	this.name      = name;
	this.onChange  = null;
	this.template  = "";
	this.type      = type;
	this.XSL       = "";
	this.mouseDown = false;
	this.gone      = false;
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.setType = function( type )
{
	this.type = type;
	
	this.refresh();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.getDate = function()
{
	return months[this.date.getMonth()] + " " + this.date.getFullYear();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.gotoYear = function( year )
{
	var
		href = new String( document.location.href );
	
	if ( href.indexOf("/") > -1 )
		href = href.substr( href.lastIndexOf("/") );
	
	if ( href.match( /([\?\&]calYear=)(\d.)/gi ) )
		href = href.replace( /([\?\&]calYear=)(\d+)/gi, "$1" + year );
	else if ( href.indexOf("?") > -1 )
		href = href + "&calYear=" + year;
	else
		href = href + "?calYear=" + year;
	
	this.gone = true;
	
	document.location.href = href;
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.setDate = function( date )
{
	if ( this.gone ) 
		return;
	
	var
		oldYear = this.date.getYear();
	
	if ( this.type == ctWeek || this.type == ctCustom )
		this.type = ctDay;
	
	if ( this.type == ctMonth )
		this.type = ctWeek;
	
	this.date = date;
	
	this.refresh();
	
	if ( oldYear != this.date.getYear() )
		this.gotoYear( this.date.getYear() );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.add = function( ID, title, teaser, beginDate, endDate )
{
	if ( endDate == null )
	{
		endDate = new Date( beginDate );
		endDate.setSeconds( endDate.getSeconds() + 1 );
	}
	
	var
		newItem = new TCalendarItem( this, ID, title, teaser, beginDate, endDate );
	
	this.items[this.items.length] = newItem;
	this.count++;
	
	beginDate.setHours( 0 );
	beginDate.setMinutes( 0 );
	beginDate.setSeconds( 0 );
	beginDate.setMilliseconds( 0 );
	
	endDate.setHours( 0 );
	endDate.setMinutes( 0 );
	endDate.setSeconds( 0 );
	endDate.setMilliseconds( 0 );
	
	for ( var i = beginDate; i < endDate.nextDay(); i = i.nextDay() )
		this.dates[i] = true;
	
	return newItem;
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.prior = function()
{
	if ( this.gone ) 
		return;
	
	var
		oldYear = this.date.getYear() 
	
	this.date = this.date.priorMonth();
	
	if ( this.type == ctCustom )
	{
		this.beginDate = this.beginDate.priorMonth();
		this.endDate   = this.endDate.priorMonth();
	}
	
	this.refresh();

	if ( oldYear != this.date.getYear() )
		this.gotoYear( this.date.getYear() );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.next = function()
{
	if ( this.gone ) 
		return;
	
	var
		oldYear = this.date.getYear() 
	
	this.date = this.date.nextMonth();
	
	if ( this.type == ctCustom )
	{
		this.beginDate = this.beginDate.nextMonth();
		this.endDate   = this.endDate.nextMonth();
	}
	
	this.refresh();
	
	if ( oldYear != this.date.getYear() )
		this.gotoYear( this.date.getYear() );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.refresh = function()
{
	if ( this.type != ctCustom )
	{
		this.beginDate = new Date( this.date );
		
		switch ( this.type )
		{
			case ctWeek :
				if ( this.dayNo( this.beginDate ) )
					this.beginDate = this.beginDate.priorDay( this.dayNo( this.beginDate ) );
				break;
			case ctMonth :
				this.beginDate.setDate( 1 );
				break;
		}
		
		this.beginDate.setHours( 0 );
		this.beginDate.setMinutes( 0 );
		this.beginDate.setSeconds( 0 );
		this.beginDate.setMilliseconds( 0 );
		
		this.endDate = new Date( this.beginDate );
		
		switch ( this.type )
		{
			case ctDay :
				this.endDate = this.endDate.nextDay();
				break;
			case ctWeek :
				this.endDate = this.endDate.nextWeek();
				break;
			case ctMonth :
				this.endDate = this.endDate.nextMonth();
		}
	}
	
	var
		count = this.redraw();
	
	if ( this.onChange ) 
		this.onChange( this, count );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.redraw = function( refreshItems )
{
	if ( refreshItems == undefined )
		refreshItems = true;
	
	var
		button = document.getElementById( TCalendarType[this.type] );
			
	if ( button ) 
		button.checked = true;
	else
		for ( var i = ctDay; i < ctCustom; i++ )
		{
			var
				button = document.getElementById( TCalendarType[i] );
			
			if ( button ) 
				button.checked = false;
		}	
		
	var
		dateDiv = document.getElementById( this.dateDiv ), 
		count   = 0;
	
	if ( dateDiv )
		dateDiv.innerHTML = this.getDate();
	
	if ( refreshItems )
		for ( var i = 0; i < this.items.length; i++ )
		{
			var
				item = this.items[i], 
				div  = document.getElementById("itmID_" + item.ID );
			
			if ( div )
			{
				div.style.display = ( item.getShow() ? "" : "none");
				
				if ( item.getShow() )
					count++;
			}
		}
	
	this.calendar();
	
	setCookie("calType",      this.type + 1, null );
	setCookie("calDate",      this.date.getDate()      + "-" + (this.date.getMonth() + 1)      + "-" + this.date.getFullYear(), null );
	setCookie("calBeginDate", this.beginDate.getDate() + "-" + (this.beginDate.getMonth() + 1) + "-" + this.beginDate.getFullYear(), null );
	setCookie("calEndDate",   this.endDate.getDate()   + "-" + (this.endDate.getMonth() + 1)   + "-" + this.endDate.getFullYear(), null );
	
	return count;
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.write = function()
{
	var
		div = document.getElementById( this.mainDiv );
	
	if ( div )
	{
		if ( this.template.length )
		{
			var
				HTML = new Array();
			
			for ( var i = 0; i < this.items.length; i++ )
			{
				var
					idx  = HTML.length;
				
				HTML[idx] = this.template;
				
				var
					matches = HTML[idx].match( /\{([^\}]+)\}/gi );
				
				for ( var j = 0; j < matches.length; j++ )
				{
					var
						value = eval("this.items[" + i + "]." + matches[j].substr( 1, matches[j].length - 2 ) );
					
					HTML[idx] = HTML[idx].replace( new RegExp( replacePar( matches[j] ), "g"), value );
				}
			}
			
			div.innerHTML = HTML.join("");
		}
		else if ( this.XSL.length )
		{
			var
				XML = new ActiveXObject("MSXML2.DOMDocument.3.0"), 
				XSL = new ActiveXObject("MSXML2.DOMDocument.3.0");
			
			XSL.loadXML( this.XSL );
			XML.loadXML( this.createXML() );
			
			div.innerHTML = XML.transformNode( XSL );
		}
	}
	
	this.refresh();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.dayNo = function( date )
{
	return ( date.getDay() < firstDay ? (7 - firstDay) + date.getDay() : date.getDay() - firstDay );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.getClassName = function( date )
{
	var
		retVal;
	
	if ( date.getMonth() < this.date.getMonth() || 
		  date.getMonth() > this.date.getMonth() )
	{
		retVal = "calDayOM";
		
		if ( this.beginDate <= date && date < this.endDate )
				retVal += " calSelectedOM";
	}
	else
	{
		retVal = "calDay";
		
		if ( this.beginDate <= date && date < this.endDate )
				retVal += " calSelected";
	}
	
	if ( date.isSameDate( new Date() ) )
		retVal += " calToday";
	
	if ( this.dates[date] )
		retVal += " calFilled";
	
	return retVal;
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.calendar = function()
{
	var
		div = document.getElementById( this.calDiv );
	
	if ( div )
	{
		var
			year     = this.date.getFullYear(), 
			month    = this.date.getMonth(), 
			date     = new Date( year, month, 1 ), 
			dayNo    = this.dayNo( date ), 
			endDate  = date.nextMonth(), 
			tableStr = 
					"<table id=\"tblCal\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\r\n" + 
					"\t<tr>\r\n" + 
					"\t\t<td></td>\r\n";
		
		for ( var i = firstDay; i < 7; i++ )
			tableStr += 
					"\t\t<td class=\"calDayHeader\">" + days[i].substr(0, 1) + "</a></td>\r\n";
		
		for ( var i = 0; i < firstDay; i++ )
			tableStr += 
				"\t\t<td class=\"calDayHeader\">" + days[i].substr(0, 1) + "</td>\r\n";
		
		tableStr += 
				"\t</tr>\r\n" + 
				"\t<tr><td class=\"calWeekNo\" onclick=\"" + this.name + ".setDate( " + date.jsDate() + " );" + this.name + ".setType( ctWeek );\" onmouseover=\"this.className='calWeekNo calSel';\" onmouseout=\"this.className='calWeekNo';\">" + date.priorDay( dayNo ).weekNo() + "</td>";
		
		for ( var i = dayNo; i > 0; i-- )
		{
			var
				prior = date.priorDay( i );
			
			tableStr += "<td onmousedown=\"" + this.name + ".onMouseDown( " + prior.jsDate() + " );\" onmouseover=\"" + this.name + ".onMouseOver( " + prior.jsDate() + " );\" onmouseup=\"" + this.name + ".onMouseUp();\" class=\"" + this.getClassName( prior ) + "\">" + prior.formatDate("d") + "</td>";
		}
		
		while ( date < endDate )
		{
			tableStr += "<td onmousedown=\"" + this.name + ".onMouseDown( " + date.jsDate() + " );\" onmouseover=\"" + this.name + ".onMouseOver( " + date.jsDate() + " );\" onmouseup=\"" + this.name + ".onMouseUp();\" class=\"" + this.getClassName( date ) + "\">" + date.formatDate("d") + "</td>";
			
			date  = date.nextDay();
			dayNo = this.dayNo( date );
			
			if ( date < endDate && dayNo == 0 )
				tableStr += "\t<tr><td class=\"calWeekNo\" onclick=\"" + this.name + ".setDate( " + date.jsDate() + " );" + this.name + ".setType( ctWeek );\" onmouseover=\"this.className='calWeekNo calSel';\" onmouseout=\"this.className='calWeekNo';\">" + date.weekNo() + "</td>";
		}
		
		if ( dayNo )
		{
			for ( var i = 0; i < 20 && dayNo < 7; date = date.nextDay(), i++ )
			{
				tableStr += "<td onmousedown=\"" + this.name + ".onMouseDown( " + date.jsDate() + " );\" onmouseover=\"" + this.name + ".onMouseOver( " + date.jsDate() + " );\" onmouseup=\"" + this.name + ".onMouseUp();\" class=\"" + this.getClassName( date ) + "\">" + date.formatDate("d") + "</td>";
				dayNo++;
			}
		}
		
		tableStr += 
				"</table>";
		
		div.innerHTML = tableStr;
	}	
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.onMouseDown = function( date )
{
	if ( this.gone ) 
		return;
	
	var
		oldYear = this.date.getYear();
	
	this.date      = new Date( date );
	this.beginDate = new Date( date );
	this.endDate   = date.nextDay();
	this.mouseDown = true;
	
	this.refresh();
	
	if ( oldYear != this.date.getYear() )
		this.gotoYear( this.date.getYear() );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.onMouseOver = function( date )
{
	if ( this.gone ) 
	{
		this.mouseDown = false;
		return;
	}
	
	this.beginDate = new Date( this.date );

	if ( this.mouseDown && ! date.nextDay().isSameDate( this.endDate ) ) 
	{
		this.endDate = date.nextDay();
		
		if ( this.endDate <= this.beginDate )
		{
			date           = new Date( this.endDate );
			this.endDate   = this.beginDate.nextDay();
			this.beginDate = date.priorDay();
		}
				
		if ( this.beginDate.nextDay().isSameDate( this.endDate ) )
			this.type = ctDay;
		else if ( this.beginDate.nextDay( 7 ).isSameDate( this.endDate ) && 
					 this.beginDate.getDay() == firstDay )
			this.type = ctWeek;
		else if ( this.beginDate.getDate() == 1 && 
					 this.beginDate.nextMonth().isSameDate( this.endDate ) )
			this.type = ctMonth;
		else
			this.type = ctCustom;
		
		this.redraw( false ); 
	}
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.onMouseUp = function()
{
	this.mouseDown = false;
	this.refresh();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.createXML = function()
{
	var
		XML = 
				"<?xml version=\"1.0\"?>\r\n" +
				"<root steID=\"" + steID + "\">\r\n" + 
				"\t<imgRoot>" + imgRoot + "</imgRoot>\r\n" + 
				"\t<items>\r\n";
	
	for ( var i = 0; i < this.items.length; i++ )
		XML += this.items[i].createXML();
	
	XML += 
				"\t</items>\r\n" + 
				"</root>\r\n";
	
	return XML;
}
//=================================================================================================
TCalendarItem = function( owner, ID, title, teaser, beginDate, endDate )
{
	this.className = "TCalendarItem";
	this.owner     = owner;
	this.ID        = ID;
	this.title     = title;
	this.teaser    = teaser;
	this.beginDate = new Date( beginDate );
	this.endDate   = new Date( endDate );
	this.imgRoot   = imgRoot;
}
//=================================================================================================
TCalendarItem.prototype.getShow = function()
{
	var
		show = 
				(this.beginDate <  this.owner.beginDate && this.endDate   > this.owner.beginDate) ||
				(this.beginDate >= this.owner.beginDate && this.beginDate < this.owner.endDate  );
	
	return show;
}
//=================================================================================================
TCalendarItem.prototype.getDisplay = function()
{
	if ( this.getShow() )
		return "";
	else
		return " style=\"display:none;\"";
}
//=================================================================================================
TCalendarItem.prototype.formatDate = function()
{
	var 
		retVal;
	
	if ( this.beginDate.getHours() == 0 && this.beginDate.getMinutes() == 0 && this.beginDate.getSeconds() == 0 )
		retVal = 
				this.beginDate.getDate() + " " + months[this.beginDate.getMonth()] + " " + this.beginDate.getYear();
	else
		retVal = 
				this.beginDate.getDate() + " " + months[this.beginDate.getMonth()] + " " + this.beginDate.getYear() + " " + 
				this.beginDate.getHours() + ":" + fillOut( this.beginDate.getMinutes() );
	
	if ( this.beginDate.getDate()  == this.endDate.getDate() && 
		  this.beginDate.getMonth() == this.endDate.getMonth() &&
		  this.beginDate.getYear()  == this.endDate.getYear() )
	{
		if ( this.beginDate.getHours()   != this.endDate.getHours() ||
			  this.beginDate.getMinutes() != this.endDate.getMinutes() )
		{
			if ( this.endDate.getHours() != 0 || this.endDate.getMinutes() != 0 || this.endDate.getSeconds() != 0 )
				retVal += " - " + 
						this.endDate.getHours() + ":" + fillOut( this.endDate.getMinutes() );
		}
	}
	else if ( this.endDate.getHours() == 0 && this.endDate.getMinutes() == 0 && this.endDate.getSeconds() == 0 )
	{ 
		retVal += " - " +  
				this.endDate.getDate() + " " + months[this.endDate.getMonth()] + " " + this.endDate.getYear();
	}
	else
	{ 
		retVal += " - " +  
				this.endDate.getDate() + " " + months[this.endDate.getMonth()] + " " + this.endDate.getYear() + " " + 
				this.endDate.getHours() + ":" + fillOut( this.endDate.getMinutes() );
	}
	
	return retVal;
}
//=================================================================================================
TCalendarItem.prototype.createXML = function()
{
	var
		XML = 
				"\t\t<item ID=\"" + this.ID + "\" show=\"" + ( this.getShow() ? "1" : "0") + "\">\r\n" + 
				"\t\t\t<title><![CDATA[" + this.title + "]]></title>\r\n" + 
				"\t\t\t<teaser><![CDATA[" + this.teaser + "]]></teaser>\r\n" + 
				"\t\t\t<date>" + this.formatDate() + "</date>\r\n" + 
				"\t\t</item>\r\n";
	return XML;
}
//=================================================================================================
