var NUM_EXTRA_WEEKS_PRELOAD = 7;
var NUM_WEEKS_BEFORE_END_THRESHOLD = 3;

var calendarStatus = new Array();
var calendarDayData = new Array();
var calendarMinDateInCache = new Array();
var calendarMaxDateInCache = new Array();
var calendarDataDivs = new Array();
var calendarServerUrl = new Array();
//var calendarAjax = new Array();
var calendarDayInfoAjax = new Array();
var calendarDayInfoUrl = new Array();
var calendarDayInfoIdParam = new Array();

function calendarIsDivClicked(divName,e) {
	if (divName != null) {
		if (document.layers) {
			var clickX = e.pageX;
			var clickY = e.pageY;
			var t = document.layers[divName];
			if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
				return true;
				}
			else { return false; }
			}
		else if (document.all) { // Need to hard-code this to trap IE for error-handling
			var t = window.event.srcElement;
			while (t.parentElement != null) {
				if (t.id==divName) {
					return true;
					}
				t = t.parentElement;
				}
			return false;
			}
		else if (document.getElementById && e) {
			var t = e.originalTarget;
			while (t.parentNode != null) {
				if (t.id==divName) {
					return true;
					}
				t = t.parentNode;
				}
			return false;
			}
		return false;
		}
	return false;
}
	
function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

function calendarCloseDataDivs(e) {
	for(var id in calendarDataDivs) {
		if (!calendarIsDivClicked('dataPopup'+id,e))
			calendarRemoveDataDivs(id);
	}
}
function calendarRemoveDataDivs(id) {
	if (calendarDataDivs[id] != null) {
		document.body.removeChild(calendarDataDivs[id]);
		calendarDataDivs[id] = null;
	}
}

function calendarGotDayInfo(response, node, param) {
	if (response != null) {
		var div = document.getElementById('dataPopup'+param);
		if (div != null) {
			var years = response.getElementsByTagName('year');
			if (years.length == 0) return;
			var year = years[0].attributes.getNamedItem('value').nodeValue;
			var months = years[0].getElementsByTagName('month');
			if (months.length == 0) return;
			var month = months[0].attributes.getNamedItem('value').nodeValue;
			var days = months[0].getElementsByTagName('day');
			if (days.length == 0) return;
			var day = days[0].attributes.getNamedItem('value').nodeValue;
			var str = '<span class="data-small">'+day+'/'+month+'/'+year+'</span><br />';
			var acts = response.getElementsByTagName('act');
			if (acts.length > 0) str += '<span class="normal-text-small-bold">Activitats:</span><br />';
			for(var i=0;i<acts.length;i++) {
				var url = acts[i].attributes.getNamedItem('url');				
				if (url == null) {
					var id = acts[i].attributes.getNamedItem('id').nodeValue;
					url = calendarDayInfoUrl[param]+'&cid='+id;
				} else url = url.nodeValue;
				var name = calendarGetNodeInnerText(acts[i]);
				var jAtr = acts[i].attributes.getNamedItem('joined');
				var joined = (jAtr != null ? (jAtr.nodeValue == 'yes') : false);
				str += '&bull;&nbsp;<a href="'+Url.decode(url)+'" class="'+(joined ? 'joined-event-name' : 'normal-text-small')+'">'+name+'</a><br />';
			}
			acts = response.getElementsByTagName('cou');
			if (acts.length > 0) str += '<span class="normal-text-small-bold">Cursos del Col&middot;legi:</span><br />';
			for(var i=0;i<acts.length;i++) {
				var url = acts[i].attributes.getNamedItem('url');
				if (url == null) {
					var id = acts[i].attributes.getNamedItem('id').nodeValue;
					url = calendarDayInfoUrl[param]+'&cid='+id;
				} else url = url.nodeValue;
				var name = calendarGetNodeInnerText(acts[i]);
				var jAtr = acts[i].attributes.getNamedItem('joined');
				var joined = (jAtr != null ? (jAtr.nodeValue == 'yes') : false);
				str += '&bull;&nbsp;<a href="'+Url.decode(url)+'" class="'+(joined ? 'joined-event-name' : 'normal-text-small')+'">'+name+'</a><br />';
			}
			acts = response.getElementsByTagName('wks');
			if (acts.length > 0) str += '<span class="normal-text-small-bold">Altres cursos:</span><br />';
			for(var i=0;i<acts.length;i++) {
				var url = acts[i].attributes.getNamedItem('url');
				if (url == null) {
					var id = acts[i].attributes.getNamedItem('id').nodeValue;
					url = calendarDayInfoUrl[param]+'&cid='+id;
				} else url = url.nodeValue;
				var name = calendarGetNodeInnerText(acts[i]);
				str += '&bull;&nbsp;<a href="'+Url.decode(url)+'" class="normal-text-small">'+name+'</a><br />';
			}
			acts = response.getElementsByTagName('rt');
			if (acts.length > 0) str += '<span class="normal-text-small-bold">Taules rodones:</span><br />';
			for(var i=0;i<acts.length;i++) {
				var url = acts[i].attributes.getNamedItem('url');
				if (url == null) {
					var id = acts[i].attributes.getNamedItem('id').nodeValue;
					url = calendarDayInfoUrl[param]+'&cid='+id;
				} else url = url.nodeValue;
				var name = calendarGetNodeInnerText(acts[i]);
				str += '&bull;&nbsp;<a href="'+Url.decode(url)+'" class="normal-text-small">'+name+'</a><br />';
			}
			div.innerHTML = str;
		}
	}
}

function calendarPopUpDayData(id,e) {	
	if (!e) { if (window.event) e = window.event; else return; }
	var c = e.currentTarget ? e.currentTarget: null;
	if (c == null) {
		var c = e.srcElement ? e.srcElement : e.target;
		if (c == null) return;
		while(c.id == null || c.id.substr(0,2) != 'cd') c = c.parentNode;
	}
		
	var d=c.d;
	var m=c.m;
	var y=c.y;	
//	alert(id+':'+d+'/'+m+'/'+y);
//	alert(calendarDayData[id]['2008']);

	var data = calendarDayData[id][y][m][d];
	
	calendarRemoveDataDivs(id);
	
	var ddiv = document.createElement('div');
	calendarDataDivs[id] = ddiv;
	ddiv.setAttribute('id', 'dataPopup'+id);
	ddiv.style.position = 'absolute';
	ddiv.style.left = findPosX(c)+10+'px';
	ddiv.style.top = findPosY(c)+10+'px';
	ddiv.className = 'cal-data-div';
	ddiv.style.zIndex = 3;
	document.body.appendChild(ddiv);
	
	var day = y+'-'+m+'-'+d;
	calendarDayInfoAjax[id].loadXMLDoc(calendarServerUrl[id]+'?d0='+day+'&d1='+day+'&i=y',null,null,calendarGotDayInfo,id);
}

function calendarFindDayInCache(id,date) {
	var dayData = calendarDayData[id];	
	var year = date.getFullYear();
	for(var y in dayData) {
		if (y == year) {
			var month = date.getMonth()+1;
			for(var m in dayData[y]) {
				var day = date.getDate();
				if (m == month) {
					for(var d in dayData[y][m]) {
						if (d == day) return dayData[y][m][d];
					}
				}
			}
		}
	}
	return null;
}

function calendarMarkDays(id) {
	var firstDate = calendarStatus[id]['firstDate'];
	var firstMs = firstDate.getTime();
	var testDate = new Date();
	for(var y=0;y<7;y++) {
		for(var x=0;x<7;x++) {
			testDate.setTime(firstMs + (y*7+x)*24*60*60*1000);
			var c = document.getElementById('cd'+id+x+y);
			if (c != null) {
				var day = calendarFindDayInCache(id,testDate);
				if (day != null) {
					c.y=testDate.getFullYear();
					c.m=''+(testDate.getMonth()+1);
					c.d=''+(testDate.getDate());
					if (c.m.length < 2) c.m = '0'+c.m;
					if (c.d.length < 2) c.d = '0'+c.d;
					c.className += (day == 'joined') ? '-mj' : '-m';
					c.onclick=function(e) {calendarPopUpDayData(id,e);};
				} 
			}
		}
	}
/*	var firstDate = calendarStatus[id]['firstDate'];
	var firstMs = firstDate.getTime();
	var dayData = calendarDayData[id];
	for(var y in dayData) {
		for(var m in dayData[y]) {
			for(var d in dayData[y][m]) {
				var testDate = new Date(2000+parseInt(y,10),parseInt(m,10)-1,parseInt(d,10),firstDate.getHours(),firstDate.getMinutes(),firstDate.getSeconds(),firstDate.getMilliseconds());
				var testMs = testDate.getTime(); 
				var msOff = testMs - firstMs;
				if (msOff >= 0 && msOff < 7*7*24*60*60*1000) {
					var row = Math.floor((msOff+0.0)/(7*24*60*60*1000));
					var col = Math.round((msOff - row*7*24*60*60*1000)/(24*60*60*1000));
					var c = document.getElementById('cd'+id+col+row);
					if (c != null) {
						c.className += '-m';
						c.d=d;c.m=m;c.y=y;
						c.onclick=function(e) {calendarPopUpDayData(id,e);};
					}
				}
			}
		}
	}
*/
}

var calendarHandlersStarted = false;

function initEventCalendar(id, url, diUrl, diParam) {
	calendarStatus[id] = new Array();
	calendarDayData[id] = new Array();
	calendarServerUrl[id] = url;
//	calendarAjax[id] = new Ajax();
	calendarMinDateInCache[id] = '';
	calendarMaxDateInCache[id] = '';	
	calendarDayInfoAjax[id] = new Ajax();
	calendarDayInfoUrl[id] = diUrl;
	calendarDayInfoIdParam[id] = diParam
	
	if (!calendarHandlersStarted) {
		if (document.layers) {
			document.captureEvents(Event.MOUSEUP);			
		}
		if (window.addEventListener)
		document.addEventListener("mouseup", calendarCloseDataDivs, false);
		else if (window.attachEvent)
		document.attachEvent("onmouseup", calendarCloseDataDivs);
		else if (document.getElementById)
		document.onmouseup=calendarCloseDataDivs;
		
		calendarHandlersStarted = true;
	}
	
/*calendarDayData[id]['2008'] = new Array();
calendarDayData[id]['2008']['6'] = new Array();
calendarDayData[id]['2008']['6']['3'] = '<span class="data-small">Esdeveniments del 03/06/2008</span><br /><span class="normal-text-small-bold">Activitats:</span><br /><a class="normal-text-small" href="?doc=activitats/show_cat.php&cid=47">Ejemplo de actividad</a></p>';
calendarDayData[id]['2008']['6']['20'] = '<span class="data-small">Esdeveniments del 03/06/2008</span><br /><span class="normal-text-small-bold">Activitats:</span><br /><a class="normal-text-small" href="?doc=activitats/show_cat.php&cid=56">Una altra activitat</a></p>';*/

	eventCalendarSetCenterDate(id,new Date());	
}

var monthNumToStr = new Array('GEN ', 'FEB ', 'MARĒ', 'ABR ', 'MAIG', 'JUNY', 'JUL ', 'AGO ', 'SET ', 'OCT ' , 'NOV ', 'DES ');
var monthDots = new Array('','','','','','','','','','','','');

function updateEventCalendar(id) {
	new Mutex(new updateEventCalendarMutex(), "go", new Array(id));		
}

function updateEventCalendarMutex() {
	this.id = ++NEXT_CMD_ID;
	this.go = function(arguments) {
		var id = arguments[0];
		var today = new Date();
		var firstDate = new Date();
		firstDate.setTime(calendarStatus[id]['firstDate'].getTime());
		var nextDate = new Date();
		var nextWeek = new Date();
		var monthStr = '';
		var months = new Array();
		var years = new Array();
		for(var y = 0; y < 7; y++) {
			for (var x = 0; x < 7; x++) {
				var c = document.getElementById('cd'+id+(''+x)+(''+y));
				if (c != null) {
					c.className = c.className.replace('-mj','');
					c.className = c.className.replace('-m','');
					c.onclick = null;
					if (firstDate.getDate() != today.getDate() || firstDate.getMonth() != today.getMonth() || firstDate.getYear() != today.getYear())
						c.innerHTML = firstDate.getDate();
					else
						c.innerHTML = '<span class="cal-today">'+firstDate.getDate()+'</span>';
					nextWeek.setTime(firstDate.getTime() + 7 * 24 * 60 * 60 * 1000);
					if (nextWeek.getMonth() != firstDate.getMonth()) {
						if (y < 6 && c.className.indexOf('-lb') == -1)
							c.className += '-lb';					
					} else {
						c.className = c.className.replace('-lb','')
					}
					nextDate.setTime(firstDate.getTime() + 24 * 60 * 60 * 1000);
					if (nextDate.getMonth() != firstDate.getMonth()) {
						if (x < 6 && c.className.indexOf('-lr') == -1)
							c.className += '-lr';
					} else {
						c.className = c.className.replace('-lr','')
					}
				}
				if (x == 6) {
					months[months.length] = firstDate.getMonth();
					years[years.length] = (''+firstDate.getFullYear()).substr(2) + '<br />&nbsp;<br />';
				}
				firstDate.setTime(nextDate.getTime());
			}
		}
		var monthCtrl = document.getElementById('cal_month'+id);
		if (monthCtrl != null) {
			var breakPos = new Array(), firstYear;
			var mla = new Array();
			var first = false;
			for(var i = 0; i < months.length-1; i++) {
				if (months[i] != months[i+1]) {
					breakPos[breakPos.length] = i+1;
					var mname;
					var pos;
					if (!first) {
						mname = monthNumToStr[months[i]];
						pos = mname.length - 1;
						for(var j=i;j>=0;j--) {
							mla[j] = mname.charAt(pos--);
							if (j==i) { mla[j] += monthDots[months[i]] + ' ' + years[i]; };
						}
						first = true;
					}
					mname = monthNumToStr[months[i+1]];
					for(var j=0;j<mname.length&&j<months.length;j++) {
						mla[mla.length] = mname.charAt(j);
					}
					if (j==mname.length) mla[mla.length-1] += monthDots[months[i+1]] + ' ' + years[i];
				}
			}
			var str = '';
			var type = (months[0]%2);
			if (type == 0)
				str += '<span class="cal-month-even">';
			else
				str += '<span class="cal-month-odd">';
			var tagOpen = true;
			var bp = 0;
			for(var i = 0; i <= 4; i++) {
				if (bp < breakPos.length && i == breakPos[bp]) {
					bp++;
					if (tagOpen) {
						str += '</span>';
						tagOpen = false;
					}
					type=(type+1)%2;
					if (type == 0)
						str += '<span class="cal-month-even">';
					else
						str += '<span class="cal-month-odd">';
					tagOpen = true;				
				}
				if (i >= 1) {
					if (str != '') str += ' ';
					str += mla[i];
//					if (mla[i] == 'I') str += '&nbsp;';
				}
			}
			if (tagOpen) {
				str += '</span>';
				tagOpen = false;
			}
	
			monthCtrl.innerHTML = str;
		}
		calendarMarkDays(id);
	}
}

var NEXT_CMD_ID = 0;	// unique id for mutex functions
	
function calendarGotData(response,node,param) {
	new Mutex(new calendarGotDataMutex(), "go", new Array(response, node, param));		
}

function calendarGetNodeInnerText(node) {
	if (navigator.appVersion.indexOf("MSIE")!=-1) {
		// If Explorer use custom method
		return node.text;
	}
	else {
		// Use W3C method (it works with Firefox and others)
		return node.textContent;
	}
}
	
function calendarGotDataMutex() {
	this.id = ++NEXT_CMD_ID;
	this.go = function(arguments) {
		var response = arguments[0];
		var node = arguments[1];
		var param = arguments[2];
		if (response != null) {
			var root = response.getElementsByTagName('root');
			var years = root[0].getElementsByTagName('year');
			for(var y = 0; y < years.length; y++) {			
				var year = years[y].attributes.getNamedItem("value").nodeValue;
				if (calendarDayData[param][year] == null) {
					calendarDayData[param][year] = new Array();
				}
				var months = years[y].getElementsByTagName('month');			
				for (var m=0;m<months.length;m++) {
					var month = months[m].attributes.getNamedItem("value").nodeValue;
					if (calendarDayData[param][year][month] == null) {
						calendarDayData[param][year][month] = new Array();
					}
					var days=months[m].getElementsByTagName('day');
					for(var d=0;d<days.length;d++) {
						var day = days[d].attributes.getNamedItem("value").nodeValue;
						var jVar = days[d].attributes.getNamedItem("joined");
						var joined = (jVar != null ? (jVar.nodeValue == 'yes') : false);
						if (calendarDayData[param][year][month][day] == null) {
							calendarDayData[param][year][month][day] = joined ? 'joined' : ''; //calendarGetNodeInnerText(days[d]);
						}
	//					alert(day+'/'+month+'/'+year);
					}
				}
			}
			updateEventCalendar(param);
		}
	}
}

function calendarCacheData(id,minDate,maxDate) {
//	alert(new Date(minDate)+' -> '+new Date(maxDate));
	var dt = new Date();
	dt.setTime(minDate);
	var d0 = dt.getFullYear()+'-'+(dt.getMonth()+1)+'-'+dt.getDate();
	dt.setTime(maxDate);
	var d1 = dt.getFullYear()+'-'+(dt.getMonth()+1)+'-'+dt.getDate();
	var ajax = new Ajax();
	ajax.loadXMLDoc(calendarServerUrl[id]+'?d0='+d0+'&d1='+d1,null,null,calendarGotData,id);
	if (minDate < calendarMinDateInCache[id]) calendarMinDateInCache[id] = minDate;
	if (maxDate > calendarMaxDateInCache[id]) calendarMaxDateInCache[id] = maxDate;
}

function eventCalendarSetCenterDate(id, today) {
	var todayDayOfWeek = today.getDay() - 1;
	if (todayDayOfWeek < 0) todayDayOfWeek = 6;
	var firstDate = new Date();
	firstDate.setTime(today.getTime() - (todayDayOfWeek + 7 * 2) * 24 * 60 * 60 * 1000);
	calendarStatus[id]['firstDate'] = firstDate;
	eventCalendarAddStartWeek(id,0);
}

function eventCalendarAddStartWeek(id, numWeeks) {
	var firstDate = calendarStatus[id]['firstDate'];
	firstDate.setTime(firstDate.getTime() + numWeeks * 7 * 24 * 60 * 60 * 1000);
	var firstMs = firstDate.getTime();

	if (calendarMinDateInCache[id] == '') {
		calendarMinDateInCache[id] = firstMs - NUM_EXTRA_WEEKS_PRELOAD*7*24*60*60*1000;
		calendarMaxDateInCache[id] = firstMs + ((7+NUM_EXTRA_WEEKS_PRELOAD)*7-1)*24*60*60*1000;
		calendarCacheData(id,calendarMinDateInCache[id],calendarMaxDateInCache[id]);		
	} else {
		var lastShowingDateMs = firstMs + (7*7-1)*24*60*60*1000;
		var thresholdMs = NUM_WEEKS_BEFORE_END_THRESHOLD*7*24*60*60*1000;
		var extraMs = NUM_EXTRA_WEEKS_PRELOAD*7*24*60*60*1000;
		if (lastShowingDateMs > (calendarMaxDateInCache[id] - thresholdMs)) {
			calendarCacheData(id,calendarMaxDateInCache[id],lastShowingDateMs+extraMs);
		} else if (firstMs < (calendarMinDateInCache[id] + thresholdMs)) {
			calendarCacheData(id,firstMs-extraMs,calendarMinDateInCache[id]);
		}
	}
	
	updateEventCalendar(id);
}
