(function($){
		$.fn.jqueryCal = function(options){
				var defaults = {
						xmlPath: '',
						noEvents: 'No events scheduled.',
						noEventsToday: 'No events scheduled.',
						monthText: '',
						getXMLmonthly: true,
						toolTipBigPrev: "Previous Year",
						toolTipSmallPrev: "Previous Month",
						toolTipSmallNext: "Next Month",
						toolTipBigNext: "Next Year",
						showWeek: true,
						id: 0
				};
				var options = $.extend(defaults, options);
				return this.each(function(){
						// global vars
						var divID = $(this).attr("id");
						var dateList = new Array();
						var settings = {};
						var weekClasses = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
						var weekday = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
						var currentDate = new Date();
						currentDate.setHours(0);
						currentDate.setMinutes(0);
						currentDate.setSeconds(0);
						currentDate.setMilliseconds(0);
						var selectedDate = new Date();
						selectedDate.setDate(1);
						selectedDate.setHours(0);
						selectedDate.setMinutes(0);
						selectedDate.setSeconds(0);
						selectedDate.setMilliseconds(0);
						var selectedWeek = new Date();
						selectedWeek.setHours(0);
						selectedWeek.setMinutes(0);
						selectedWeek.setSeconds(0);
						selectedWeek.setMilliseconds(0);
						var tempDate = new Date();
						tempDate.setHours(0);
						tempDate.setMinutes(0);
						tempDate.setSeconds(0);
						tempDate.setMilliseconds(0);
						var clickedEventText = "";
						var todayText = "";
						var xmlPath = xmlPath;
						var tmpString = "";
						var tmpStringParts = new Array();
						var datesInWeek = new Array();
						var htmlString = "";
						
						writeHTML();
						
						// parse XML
						function parseXML(){
								try {
									var ajax_vars = {};
									ajax_vars['method'] = 'buildEventsXML';
									ajax_vars['year'] = selectedDate.getFullYear();
									ajax_vars['id'] = options.id;
									ajax_vars['r'] = Math.round(Math.random() * 100000);

									if (options.getXMLmonthly) {
										ajax_vars['month'] = (selectedDate.getMonth() + 1);
									}
									xmlPath = '/_awc_ajax';
									// console.log('sending request')

										// parse XML
										$.ajax({
												type: "GET",
												url: xmlPath,
												data: ajax_vars,
												dataType: "xml",
												success: function(xml){
														// console.log('recevied xml response: ',xml)
														$(xml).find('calendardoc').each(function(i){
																dateList[i] = new Object();
																dateList[i]["dateStart"] = Date.parse($(this).children("dateStart").text());
																dateList[i]["dateEnd"] = Date.parse($(this).children("dateEnd").text());
																dateList[i]["title"] = $(this).find('title').text();
																dateList[i]["text"] = $(this).find('text').text();
																dateList[i]["link"] = $(this).find('url').text();
														})

														$(xml).find('settings').children().each(function(i){
															settings[this.tagName] = $(this).text();
														});

														fillHTML();
												},
												error: function(XMLHttpRequest, textStatus, err) {
													// console.log('error getting events xml: textStatus=',textStatus,' err=',err)
												}
										})
								} 
								catch (err) {
									// console.log('error getting events xml: ',err)
										fillHTML();
								}
						}
						
						
						// write HTML
						function writeHTML(){
								if ((divID).match("Month")) {
										htmlString += "<div class='head'><a class='bigPrev' title='" + options.toolTipBigPrev + "' href='#'></a><a class='smallPrev'	title='" + options.toolTipSmallPrev + "' href='#'></a><span class='text'></span><a class='smallNext' title='" + options.toolTipSmallNext + "' href='#'></a><a class='bigNext' title='" + options.toolTipBigNext + "' href='#'></a></div><div class='body'>";
										
										if (options.showWeek) {
											htmlString += "<div class='calendarWeekContainer'>";
											htmlString += "<span class='kw'>WK</span>";
											for (var i = 0; i <= 5; i++) {
													htmlString += "<span class='calendarWeek'></span>";
											}
											htmlString += "</div>";
										}

										htmlString += "<div class='weekDaysContainer'>";
										for (var i = 0; i <= 6; i++) {
												htmlString += "<span class='weekDays " + weekClasses[i] + "'></span>";
										}
										htmlString += "</div><div class='weekDatesContainer'>";
										for (var i = 0; i <= 41; i++) {
												var j = 0;
												j++;
												htmlString += "<span class='weekDates " + weekClasses[j] + "'></span>";
												if (j = 6) 
														j = 0;
										}
										htmlString += "</div><div class='contentBegin'></div><div class='content'></div><div class='footer'></div></div>";
										$("#" + divID).html(htmlString);
										// month
										$("#" + divID + " .head .bigPrev").click(function(e){
												selectedDate.setYear(selectedDate.getFullYear() - 1);
												tempDate.setDate(1);
												tempDate.setYear(tempDate.getFullYear() - 1);
												parseXML();
												e.preventDefault();
										});
										$("#" + divID + " .head .smallPrev").click(function(e){
												selectedDate.setMonth(selectedDate.getMonth() - 1);
												tempDate.setDate(1);
												tempDate.setMonth(tempDate.getMonth() - 1);
												parseXML();
												e.preventDefault();
										});
										$("#" + divID + " .head .smallNext").click(function(e){
												// console.log('onClick (1) selectedDate=',selectedDate)
												selectedDate.setMonth(selectedDate.getMonth() + 1);
												tempDate.setDate(1);
												tempDate.setMonth(tempDate.getMonth() + 1);
												// console.log('onClick (2) selectedDate=',selectedDate)
												parseXML();
												e.preventDefault();
										});
										$("#" + divID + " .head .bigNext").click(function(e){
												selectedDate.setYear(selectedDate.getFullYear() + 1);
												tempDate.setDate(1);
												tempDate.setYear(tempDate.getFullYear() + 1);
												parseXML();
												e.preventDefault();
										});
								}
								else 
										if ((divID).match("Week")) {
												htmlString += "<div class='head'><a class='bigPrev' title='" + options.toolTipBigPrev + "' href='#'></a><a class='smallPrev' title='" + options.toolTipSmallPrev + "' href='#'></a><span class='text'></span><a class='smallNext'	 title='" + options.toolTipSmallNext + "'	 href='#'></a><a class='bigNext' title='" + options.toolTipBigNext + "'	 href='#'></a></div><div class='body'>";
												for (var i = 0; i <= 6; i++) 
														htmlString += "<a class='date'><span class='day " + weekClasses[i] + "'></span><span class='weekday'> " + weekClasses[i] + "</span></a>";
												htmlString += "</div><div class='content'></div><div class='footer'></div>";
												$("#" + divID).html(htmlString);
												// week
												$("#" + divID + " .head .bigPrev").click(function(e){
														selectedWeek.setMonth(selectedWeek.getMonth() - 1);
														parseXML();
														e.preventDefault();
												});
												$("#" + divID + " .head .smallPrev").click(function(e){
														selectedWeek.setDate(selectedWeek.getDate() - 7);
														parseXML();
														e.preventDefault();
												});
												$("#" + divID + " .head .smallNext").click(function(e){
														selectedWeek.setDate(selectedWeek.getDate() + 7);
														parseXML();
														e.preventDefault();
												});
												$("#" + divID + " .head .bigNext").click(function(e){
														selectedWeek.setMonth(selectedWeek.getMonth() + 1);
														parseXML();
														e.preventDefault();
												});
										}
								fillHTML(true);
								parseXML();
						}
						
						
						// fill HTML
						function fillHTML(first_time){
								// console.log('fillHTML begin selectedDate=',selectedDate)
								if ((divID).match("Month")) {
										// clean HTML
										cleanHTMLMonth();
										var firstOfSelectedMonth = selectedDate.clone();
										firstOfSelectedMonth.setDate(1);
										currentDate = new Date();
										$("#" + divID + " .head .text").html(options.monthText + " " + selectedDate.getMonthName() + " " + selectedDate.getFullYear());
										for (i = 0; i <= weekClasses.length; i++) {
												$("#" + divID + " .body .weekDaysContainer .weekDays." + weekClasses[i]).text(weekClasses[i]);
										}
										var startWrite = 0;
										var j = 1;
										// if (selectedDate.getDay() == 0) {
										// 		startWrite = 6;
										// }
										// else {
										// 		startWrite = selectedDate.getDay() - 1;
										// }

										startWrite = selectedDate.getDay();


										// write calendarweeks
										var tempMonth = selectedDate.getMonth();

										// console.log('in fillHTML(2) selectedDate=',selectedDate)
										var temp_date = selectedDate.clone();
										if (options.showWeek) {
											$("#" + divID + " .body .calendarWeek").each(function(i){
													$(this).text((getCalendarWeek(temp_date.getFullYear(), temp_date.getMonth() + 1, temp_date.getDate())));
													// console.log('temp_date.setDate setting date to ',(temp_date.getDate() + 7))
													temp_date.setDate(temp_date.getDate() + 7);
											});
										}
										
										// console.log('selectedDate (1)=',selectedDate)
										selectedDate.setMonth(tempMonth);
										selectedDate.setDate(1);
										// console.log('selectedDate (2)=',selectedDate)
										$("#" + divID + " .body .weekDatesContainer .weekDates").each(function(i){
												if (startWrite <= i && j <= (daysInMonth(firstOfSelectedMonth.getMonth() + 1, firstOfSelectedMonth.getFullYear() + 1))) {
														$(this).text(j);
														$(this).addClass("pointer");
														$(this).removeClass("empty");
														$(this).hover(function(){
																$(this).addClass("hover");
														}, function(){
																$(this).removeClass("hover");
														});
														j++;
														// mark current day
														if ((selectedDate.getMonth() == currentDate.getMonth()) && (selectedDate.getFullYear() == currentDate.getFullYear()) && ($(this).text() == currentDate.getDate())) 
																$(this).addClass("currentDate");
												}
										});
										// mark events
										for (var i = 0; i <= dateList.length - 1; i++) {
												$("#" + divID + " .body .weekDatesContainer .weekDates").each(function(){
														if ($(this).text() != "") {
																tempDate.setDate($(this).text());
																if (tempDate.getTime() >= dateList[i]["dateStart"].getTime() && tempDate.getTime() <= dateList[i]["dateEnd"].getTime()) {
																		$(this).addClass("event");
																}
														}
												})
										}
										// add events, but not on the first time
										// console.log('first_time=',first_time)
										if (first_time === undefined || first_time !== true) {
											addEventInfo();
										}
								}
								else 
										if ((divID).match("Week")) {
												// clean HTML
												cleanHTMLWeek();
												// define weekstart
												selectedWeek.setDate(selectedWeek.getDate() - selectedWeek.getDay());
												// fill html
												$("#" + divID + " .head .text").html(options.monthText + " " + selectedWeek.getMonthName() + " " + selectedWeek.getFullYear());
												$("#" + divID + " .body .date .day").each(function(i){
														selectedWeek.setDate(selectedWeek.getDate() + 1);
														$(this).text(selectedWeek.getDate());
														// mark current day
														if ((selectedWeek.getMonth() == currentDate.getMonth()) && (selectedWeek.getFullYear() == currentDate.getFullYear()) && ($(this).text() == currentDate.getDate())) 
																$(this).parent().addClass("currentDate");
												})
												selectedWeek.setDate(selectedWeek.getDate() - 6);
												// mark events
												tempDate.setDate(selectedWeek.getDate());
												tempDate.setMonth(selectedWeek.getMonth());
												tempDate.setFullYear(selectedWeek.getFullYear());
												$("#" + divID + " .body .date .day").each(function(j){
														for (var i = 0; i <= dateList.length - 1; i++) {
																if (tempDate.getTime() >= dateList[i]["dateStart"].getTime() && tempDate.getTime() <= dateList[i]["dateEnd"].getTime()) {
																		$(this).parent().addClass("event");
																}
														}
														tempDate.setDate(tempDate.getDate() + 1);
												})
												addEventInfo();
										}
						}
						
						
						// clean HTML month
						function cleanHTMLMonth(){
								$("#" + divID + " .body .weekDatesContainer .weekDates").each(function(){
										$(this).text("");
										$(this).removeClass("event");
										$(this).removeClass("currentDate");
										$(this).removeClass("pointer");
										$(this).addClass("empty");
										$(this).unbind();
										$(this).click(function(){
										});
								})
								$("#" + divID + " .head .text").text = "";
						}
						
						
						// clean HTML week
						function cleanHTMLWeek(){
								$("#" + divID + " .body .date").each(function(j){
										$(this).removeClass("event");
										$(this).removeClass("currentDate");
										$(this).removeClass("pointer");
										$(this).unbind();
										$(this).click(function(){
										});
								})
								$("#" + divID + " .head .text").text = "";
						}
						
						
						// get days of month
						function daysInMonth(month, year){
								var m = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
								if (month != 2) 
										return m[month - 1];
								if (year % 4 != 0) 
										return m[1];
								if (year % 100 == 0 && year % 400 != 0) 
										return m[1];
								return m[1] + 1;
						}
						
						
						// week of year & week of month
						function getWeekOfMonth(date){
								var todayDayOfMonth = date.getDate() - 1;
								var first = new Date(date.getFullYear() + '/' + (date.getMonth() + 1) + '/01');
								var monthFirstDateDay = first.getDay();
								return Math.ceil((todayDayOfMonth + monthFirstDateDay) / 7);
						}
						
						
						// calculate CalendarWeek
						function getCalendarWeek(jahr, monat, tag){
								var datum = new Date(jahr, monat - 1, tag);
								var jh = jahr + 1;
								var kalwo = getkaldiff(datum, jh);
								while (kalwo < 1) {
										jh--;
										kalwo = getkaldiff(datum, jh);
								}
								return kalwo;
						}
						function getkaldiff(datum, jahr){
								var d4j = new Date(jahr, 0, 4);
								var wt4j = (d4j.getDay() + 6) % 7;
								var m1wjT = Math.floor(0.01 + d4j.getTime() / 864e5 - wt4j);
								var datumT = Math.floor(0.01 + datum.getTime() / 864e5);
								return Math.floor(1 + (datumT - m1wjT) / 7);
						}
						
						
						// add event info	 
						function addEventInfo(){
								if ((divID).match("Month")) {
									// console.log('addEventInfo');
									// console.log('addEventInfo called (Month) currentDate=',currentDate,' selectedDate=',selectedDate)
										if ((currentDate.getMonth() == selectedDate.getMonth()) && (currentDate.getFullYear() == selectedDate.getFullYear())) {
												todayText = "";
												for (var i = 0; i <= dateList.length - 1; i++) {
														if ((currentDate.toLocaleDateString() == dateList[i]["dateStart"].toLocaleDateString() || currentDate.getTime() >= dateList[i]["dateStart"].getTime()) && (currentDate.toLocaleDateString() == dateList[i]["dateEnd"].toLocaleDateString() || currentDate.getTime() <= dateList[i]["dateEnd"].getTime())) {
																// todayText = todayText.concat("<b>" + dateList[i]["title"] + "</b><br />" + currentDate.toLocaleDateString() + "<br />" + dateList[i]["text"] + "<br />"); // <a href class='url'>" + dateList[i]["url"] + "</a>
																todayText = todayText.concat('<span class="entry">' + dateList[i]["text"] + '</span>' + "<br />");
														}
												}
												if (todayText == "") {
														todayText = "<b>" + todayText.concat(options.noEventsToday) + "</b>";
												} else {
													// add date once
													// console.log('addDateHref: currentDate=',currentDate)
													todayText = addDateHref(currentDate.toString('M/dd/yyyy'), currentDate) + '<br />' + todayText;
													// todayText = currentDate.toLocaleDateString() + '<br />' + todayText;
												}
												$("#" + divID + " .content").html(todayText);
										}
										// add day events
										$("#" + divID + " .body .weekDatesContainer .pointer").each(function(){
											
												$(this).hover(function(){
														$(this).addClass("mouseOver");
												}, function(){
														$(this).removeClass("mouseOver");
												});
												$(this).click(function(e){
													if (settings.date_href.length) {
														selectedDate.setDate($(this).text());
														var href = buildDateHref(selectedDate);
														// console.log('$(this)=',$(this),' - on click date text=',$(this).text(),' selectedDate=',selectedDate,' href=',href);
														// return;
														if (href.length) {
															window.location = href;
															e.preventDefault();
															return;
														}
													}

														$("#" + divID + " .body .weekDatesContainer .pointer").each(function(){
																$(this).removeClass("currentDate");
														})
														$(this).addClass("currentDate");
														clickedEventText = "";
														selectedDate.setDate($(this).text());
														
														// console.log('addEventInfo processing selectedDate=',selectedDate)
														
														for (var i = 0; i <= dateList.length - 1; i++) {
																if ((selectedDate.toLocaleDateString() == dateList[i]["dateStart"].toLocaleDateString() || selectedDate.getTime() >= dateList[i]["dateStart"].getTime()) && (selectedDate.toLocaleDateString() == dateList[i]["dateEnd"].toLocaleDateString() || selectedDate.getTime() <= dateList[i]["dateEnd"].getTime())) {
																		// clickedEventText = clickedEventText.concat("<b>" + dateList[i]["title"] + "</b><br />" + selectedDate.toLocaleDateString() + "<br />" + dateList[i]["text"] + "<br />"); // <a href class='url'>" + dateList[i]["url"] + "</a>
																		clickedEventText = clickedEventText.concat('<span class="entry">' + dateList[i]["text"] + '</span>' + "<br />");
																}
														}
														// console.log('clickedEventText for selectedDate ',selectedDate,' is ',clickedEventText,'')
														if (clickedEventText == "") {
															clickedEventText = "<b>" + clickedEventText.concat(options.noEvents) + "</b>";
														} else {
															// console.log('addDateHref: selectedDate=',selectedDate)
															var date_text = addDateHref(selectedDate.toString('M/dd/yyyy'), selectedDate);
															
															// clickedEventText = '<span class="contentDate">' + selectedDate.toLocaleDateString() + '</span>' + '<br />' + clickedEventText;
															clickedEventText = '<span class="contentDate">' + date_text + '</span>' + '<br />' + clickedEventText;
														}
														$("#" + divID + " .content").html(clickedEventText);
														e.preventDefault();
												})
										});
								}
								else {
										if ((currentDate.getMonth() == selectedWeek.getMonth()) && (currentDate.getFullYear() == selectedWeek.getFullYear())) {
												todayText = "";
												for (var i = 0; i <= dateList.length - 1; i++) {
														if ((currentDate.toLocaleDateString() == dateList[i]["dateStart"].toLocaleDateString() || currentDate.getTime() >= dateList[i]["dateStart"].getTime()) && (currentDate.toLocaleDateString() == dateList[i]["dateEnd"].toLocaleDateString() || currentDate.getTime() <= dateList[i]["dateEnd"].getTime())) {
																todayText = todayText.concat("<b>" + dateList[i]["title"] + "</b><br />" + currentDate.toLocaleDateString() + "<br />" + dateList[i]["text"] + "<br />"); // <a href class='url'>" + dateList[i]["url"] + "</a>
														}
												}
												if (todayText == "") {
														todayText = "<b>" + todayText.concat(options.noEventsToday) + "</b>";
												}
												$("#" + divID + " .content").html(todayText);
										}
										// add day events
										$("#" + divID + " .body .date .day").each(function(){
												$(this).parent().hover(function(){
														$(this).addClass("mouseOver");
												}, function(){
														$(this).removeClass("mouseOver");
												});
												$(this).parent().click(function(e){
														$("#" + divID + " .body .date").each(function(){
																$(this).removeClass("currentDate");
														})
														$(this).addClass("currentDate");
														clickedEventText = "";
														selectedDate.setFullYear(selectedWeek.getFullYear());
														selectedDate.setMonth(selectedWeek.getMonth());
														var date;
														if ($(this).text().length == 5) 
																date = $(this).text().substr(0, 2);
														else 
																if ($(this).text().length == 4) 
																		date = $(this).text().substr(0, 1);
														selectedDate.setDate(date);
														$("#" + divID + " .body .date .day").each(function(){
																if ($(this).text() == daysInMonth(selectedDate.getMonth() + 1, daysInMonth(selectedDate.getFullYear()))) {
																		if (date >= 1 && date <= 7) {
																				selectedDate.setMonth(selectedDate.getMonth() + 1);
																		}
																}
														})
														for (var i = 0; i <= dateList.length - 1; i++) {
																if ((selectedDate.toLocaleDateString() == dateList[i]["dateStart"].toLocaleDateString() || selectedDate.getTime() >= dateList[i]["dateStart"].getTime()) && (selectedDate.toLocaleDateString() == dateList[i]["dateEnd"].toLocaleDateString() || selectedDate.getTime() <= dateList[i]["dateEnd"].getTime())) {
																		clickedEventText = clickedEventText.concat("<b>" + dateList[i]["title"] + "</b><br />" + selectedDate.toLocaleDateString() + "<br />" + dateList[i]["text"] + "<br />"); // <a href class='url'>" + dateList[i]["url"] + "</a>
																}
																else {
																		if ((selectedDate.toLocaleDateString() == dateList[i]["dateStart"].toLocaleDateString() || selectedDate.getTime() >= dateList[i]["dateStart"].getTime()) && (selectedDate.toLocaleDateString() == dateList[i]["dateEnd"].toLocaleDateString() || selectedDate.getTime() <= dateList[i]["dateEnd"].getTime())) {
																				clickedEventText = clickedEventText.concat("<b>" + dateList[i]["title"] + "</b><br />" + selectedDate.toLocaleDateString() + "<br />" + dateList[i]["text"] + "<br />"); // <a href class='url'>" + dateList[i]["url"] + "</a>
																		}
																}
														}
														if (clickedEventText == "") 
																clickedEventText = "<b>" + clickedEventText.concat(options.noEvents) + "</b>";
														$("#" + divID + " .content").html(clickedEventText);
														e.preventDefault();
												})
										});
								}
						}
						
						function buildDateHref(currentDate) {
							if (settings.date_href.length) {
								var tsbeg = currentDate.toString('yyyy-MM-dd');
								var endDate = currentDate.clone();
								endDate.add(1).day();
								var tsend = endDate.toString('yyyy-MM-dd');
								return settings.date_href+'?tsbeg='+tsbeg+'&tsend='+tsend;

								// var ts = Math.floor(currentDate.getTime()/1000);
								// return settings.date_href+'?tsbeg='+ts+'&tsend='+(ts+86400);
							}
							return '';
						}
						
						function addDateHref(date_text, currentDate) {
							var href = buildDateHref(currentDate);
							if (href) {
								return '<a href="'+href+'">'+date_text+'</a>';
							}
							return date_text;
						}
				});
		};
})(jQuery);
