/* (c) 2009 - Jean Luc BIELLMANN [except getWeek()] */

function twoDigits (n) {
	var number = n.toString();
	return (number.length==1 ? '0' : '')+number;
}

var objCals = {}; // global list for all calendars objects

function Cal (id,lang) {
	this.id = id;
	this.lang = lang;
	objCals[this.id] = this;
	var now = new Date();
	this.today = new Date(now.getFullYear(),now.getMonth(),now.getDate()); // forget seconds...
	this.setY(this.today.getFullYear());
	this.setM(this.today.getMonth());
	this.setD(this.today.getDate());
	//this.months = ['J','F','M','A','M','J','J','A','S','O','N','D'];
	this.months = {
		fr : ['Jan','Fév','Mar','Avr','Mai','Jui','Jul','Aoû','Sep','Oct','Nov','Déc'],
		en : ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
		de : ['Jan','Feb','Mär','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
	};
	this.week = {
		fr : {'name':'Sem','startOn':1,'days':['Dim','Lun','Mar','Mer','Jeu','Ven','Sam']},
		en : {'name':'We','startOn':0,'days':['Sun','Mon','Tue','Wed','Thu','Fri','Sat']},
		de : {'name':'Wo','startOn':1,'days':['Son','Mon','Die','Mit','Don','Fre','Sam']}
	};
	this.showYear = true;
	this.showMonths = true;
	// en
	//this.week = {'name':'Week','startOn':0,'days':['Sun','Mon','Tue','Wed','Thu','Fri','Sat']}; 
	this.init();
}
Cal.prototype = {
	init : function () {
		
		var container = $(this.id); //E('div',{'id':this.id});
		
		if (!container.hasClassName('cal'))
			container.addClassName('cal');

		if (this.showYear) {
			var d = E('div');
			A(d,[
				E('button',{'type':'button','onclick':'objCals[\''+this.id+'\'].updY(\'-5\');'}).update('<-5'),
				E('button',{'type':'button','onclick':'objCals[\''+this.id+'\'].updY(\'-1\');'}).update('<-1'),
				E('span',{'class':'cy'}),
				E('button',{'type':'button','onclick':'objCals[\''+this.id+'\'].updY(\'+1\');'}).update('+1>'),
				E('button',{'type':'button','onclick':'objCals[\''+this.id+'\'].updY(\'+5\');'}).update('+5>'),
				E('br')
			]);
			d.addClassName('year');
			A(container,d);
		}
		
		if (this.showMonths) {
			var tbody = E('tbody');
			var tr = E('tr');
			for (var m=1;m<13;m++) {
				var b = E('button',{'type':'button','value':m,'onclick':'objCals[\''+this.id+'\'].updM(\''+(m-1)+'\');'}).update(this.months[this.lang][m-1]);
				A(tr,A(E('td'),b));
				if (m==6) {
					A(tbody,tr);
					tr = E('tr');
				}
			}
			A(tbody,tr);
			A(container,A(E('table',{'class':'months'}),tbody));
		}
		
		A(container,E('div',{'class':'days'}));
		
		//this.addEvents();

		this.upd();
	},
	setY : function (y) {
		this.cy = parseInt(y,10);
	},
	setM : function (m) {
		this.cm = parseInt(m,10);
	},
	setD : function (d) {
		this.cd = parseInt(d,10);
	},
	updY : function (y) {
		var year = y.toString();
		switch (year.charAt(0)) {
			case '+' : // positive offset
				this.setY(this.cy + parseInt(year.substr(1),10));
				break;
			case '-' : // negative offset
				this.setY(this.cy - parseInt(year.substr(1),10));
				break;
			default:
				this.setY(year);
		}
		this.upd();
	},
	updM : function (m) {
		this.setM(m);
		this.upd();
	},	
	updD : function (e) {
		var obj = Event.element(e);
		//console.log('value='+obj.value);
	},	 
	getWeekDay : function (date) {
		return this.week[this.lang]['days'][date.getDay()];
	},
	daysInMonth : function (y, m) {
		return 32 - new Date(y, m, 32).getDate();
	},
	getWeek : function (year,month,day) {
		//lets calc weeknumber the cruel and hard way :D
		//Find JulianDay 
		month += 1; //use 1-12
		var a = Math.floor((14-(month))/12);
		var y = year+4800-a;
		var m = (month)+(12*a)-3;
		var jd = day + Math.floor(((153*m)+2)/5) + 
			(365*y) + Math.floor(y/4) - Math.floor(y/100) + 
			Math.floor(y/400) - 32045;      // (gregorian calendar)
		//var jd = (day+1)+Math.Round(((153*m)+2)/5)+(365+y) + 
		//                 Math.round(y/4)-32083;    // (julian calendar)

		//now calc weeknumber according to JD
		var d4 = (jd+31741-(jd%7))%146097%36524%1461;
		var L = Math.floor(d4/1460);
		var d1 = ((d4-L)%365)+L;
		var NumberOfWeek = Math.floor(d1/7) + 1;
		return NumberOfWeek;        
	},
	getCalMonth : function (cy,cm) {
		var cal = {};
		var lastday = this.daysInMonth(cm, cy);
		var wstart = this.getWeek(cy,cm,1);
		var wend = this.getWeek(cy,cm,lastday);
		var d,cdate,week,wday;
		
		for (d=1;d<=lastday;d++) {
			cdate = new Date(cy,cm,d);
			week = this.getWeek(cy,cm,d);
			if (typeof(cal['w'+week])=='undefined')
				cal['w'+week] = {};
			wday = this.getWeekDay(cdate);
			//console.log(cdate+' '+week+' '+wday);
			cal['w'+week][wday] = d;
		}

		for (d=0;d>-7;d--) {
			cdate = new Date(cy,cm,d);
			//console.log(cy+','+cm+','+d+':'+this.getWeek(cy,cm,d)+'='+wstart+'?');
			if (this.getWeek(cy,cm,d)!=wstart)
				continue;
			wday = this.getWeekDay(cdate);
			cal['w'+wstart][wday] = d;
		}
	
		for (d=lastday+1;d<lastday+7;d++) {
			cdate = new Date(cy,cm,d);
			if (this.getWeek(cy,cm,d)!=wend)
				continue;
			wday = this.getWeekDay(cdate);
			cal['w'+wend][wday] = d;
		}

		//console.debug(cal);
		return cal;
	},
	upd : function () {
		var i, w, d, cdate, wday, months, reald;
		var table,thead,tbody,tr,td,input;
		var curdate = new Date(this.cy,this.cm,this.cd);
		var cal = this.getCalMonth(this.cy,this.cm);

		if (this.showYear)
			$(this.id).select('span[class="cy"]')[0].update(this.cy);
		
		if (this.showMonths) {
			months = $(this.id).select('table[class="months"]')[0].select('button');
			months.invoke('removeClassName','cur');
			months[this.cm].addClassName('cur');
		}
		
		table = E('table');

		thead = E('thead');
		A(table,thead)

		tr = E('tr');
		A(tr,E('td',{'class':'weeknumber'}).update(this.week[this.lang]['name']))
		for (i=this.week[this.lang]['startOn'];i<this.week[this.lang]['days'].length+this.week[this.lang]['startOn'];i++)
			A(tr,E('td',{'class':'dayname'}).update(this.week[this.lang]['days'][i%7]));
		A(thead,tr)

		tbody = E('tbody');
		A(table,tbody)

		tr = E('tr');
		for (w in cal) {
			tr = E('tr');
			A(tr,E('td',{'class':'weeknumber'}).update(w.replace(/w/,'')))
			for (i=this.week[this.lang]['startOn'];i<this.week[this.lang]['days'].length+this.week[this.lang]['startOn'];i++) {
				td = E('td');
				wday = this.week[this.lang]['days'][i%7];
				d = cal[w][wday];
				//console.log(w+' '+wday+' '+d);
				reald = new Date(this.cy,this.cm,d);
				input = E('button',{
					'type':'button', 
					'value':this.YMD(this.cy,this.cm+1,d), 
					'class':(parseInt(reald-this.today,10)==0 ? ' cur' : '')+(d<1 || d>this.daysInMonth(this.cy,this.cm) ? ' transparent' : '')
				}).update(twoDigits(reald.getDate())).observe('click',(function (e) { objCals[this.id].updD(e); }).bindAsEventListener(this));
				A(td,input);
				A(tr,td);
			}
			A(table,tr);
		}	
		
		$(this.id).select('div[class="days"]')[0].update(table);
	},
	YMD : function (y,m,d) {
		return y+twoDigits(m)+twoDigits(d);
	},
	getIcalYear : function (ical) {
		return ical.substr(0,4);
	},
	getIcalMonth : function (ical) {
		return ical.substr(4,2);
	},
	getIcalDay : function (ical) {
		return ical.substr(6,2);
	}
}

