/**
 * Class Calendar
 * This class can be used as a date picker (fills in a field in a form) or a blog calendar (highlights dates and generate links to articles)
 * @author IRCF
 */

// Customize the Date and Array objects
Date.prototype.getWeek = function() {
	var onejan = new Date(this.getFullYear(),0,1);
	return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
}
Date.prototype.toString = function() {
	var day = this.getDate();
	if (day<10) day = "0" + day;
	var month = this.getMonth() + 1;
	if (month<10) month = "0" + month;
	return day + "-" + month + "-" + this.getFullYear();
}
Array.prototype.inArray = function(value) {
	for (var i = 0, l = this.length; i < l; i++){
		if (this[i] == value) return true;
	}
	return false;
}

// Define the Calendar instances and object
var Calendar = function(_options){
	// Define the default options
	this.options = {
		id : "calendar",
		currentDate : new Date(),
		startDate : new Date(new Date().getFullYear()-1,0,1),
		endDate : new Date(new Date().getFullYear()+1,0,1),
		month : ["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],
		day : ["lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"],
		week : "Sem",
		onpick : null,
		highlight : null
	}
	//Get the input options
	if (_options){
		if (_options.id) this.options.id =  _options.id;
		if (_options.currentDate) this.options.currentDate = _options.currentDate;
		if (_options.startDate) this.options.startDate = _options.startDate;
		if (_options.endDate) this.options.endDate = _options.endDate;
		if (_options.month) this.options.month = _options.month;
		if (_options.day) this.options.day = _options.day;
		if (_options.week) this.options.week = _options.week;
		if (_options.onpick) this.options.onpick = _options.onpick;
		if (_options.highlight) this.options.highlight = _options.highlight;
	}
	// Gets or create the container
	this.container = document.getElementById(this.options.id);
	if (!this.container){
		this.container = document.createElement("DIV");
		this.container.id = this.options.id;
		document.body.appendChild(this.container);
	}
	// Generate the calendar in the container
	this.generate = function(){
		// Create input buttons and select boxes
		var inputPrevious = document.createElement("INPUT");
		inputPrevious.type = "button";
		inputPrevious.value = "<";
		inputPrevious.calendar = this;
		inputPrevious.onclick = function(){this.calendar.previousMonth()};
		var selectMonth = document.createElement("SELECT");
		selectMonth.name = "month";
		selectMonth.calendar = this;
		selectMonth.onchange = function(){
			this.calendar.setMonth(this.options[this.selectedIndex].value);
		}
		for (var m=0;m<12;m++){
			var option = document.createElement("OPTION");
			option.value = m;
			option.selected = (m==this.options.currentDate.getMonth());
			option.appendChild(document.createTextNode(this.options.month[m]));
			selectMonth.appendChild(option);
		}
		var selectYear = document.createElement("SELECT");
		selectYear.name = "year";
		selectYear.calendar = this;
		selectYear.onchange = function(){
			this.calendar.setYear(this.options[this.selectedIndex].value);
		}
		for (var y=this.options.startDate.getFullYear();y<this.options.endDate.getFullYear();y++){
			var option = document.createElement("OPTION");
			option.value = y;
			option.selected = (y==this.options.currentDate.getFullYear());
			option.appendChild(document.createTextNode(y));
			selectYear.appendChild(option);
		}
		var inputNext = document.createElement("INPUT");
		inputNext.type = "button";
		inputNext.value = ">";
		inputNext.calendar = this;
		inputNext.onclick = function(){this.calendar.nextMonth()};
		// Add them into a paragraph
		var p = document.createElement("P");
		p.appendChild(inputPrevious);
		p.appendChild(selectMonth);
		p.appendChild(selectYear);
		p.appendChild(inputNext);
		// Create the calendar view
		var view = document.createElement("DIV");
		// Create the main form
		var form = document.createElement("FORM");
		form.appendChild(p);
		form.appendChild(view);
		this.container.appendChild(form);
		this.update();
	}

	// Update the calendar
	this.update = function (){
		// Create the caption
		var caption = document.createElement("CAPTION");
		caption.appendChild(document.createTextNode(this.options.month[this.options.currentDate.getMonth()]+" "+this.options.currentDate.getFullYear()));
		// Create the head
		var thead = document.createElement("THEAD");
		var tr = document.createElement("TR");
		var th = document.createElement("TH");
		th.appendChild(document.createTextNode(this.options.week));
		tr.appendChild(th);
		for (var d=0;d<7;d++){
			var th = document.createElement("TH");
			th.appendChild(document.createTextNode(this.options.day[d].substring(0,1).toUpperCase()));
			tr.appendChild(th);
		}
		thead.appendChild(tr);
		// Create the body
		var tbody = document.createElement("TBODY");
		var date = new Date(this.options.currentDate.getFullYear(),this.options.currentDate.getMonth(),1);
		for (var w=0;w<6;w++){
			var tr = document.createElement("TR");
			var th = document.createElement("TH");
			th.appendChild(document.createTextNode(date.getWeek()));
			tr.appendChild(th);
			for (var d=0;d<7;d++){
				var td = document.createElement("TD");
				if ((date.getDay()+6)%7==d && date.getMonth()==this.options.currentDate.getMonth()){
					// Day is highlighted if no highlight is defined or if current date matches a highlight date
					if (!this.options.highlight || this.options.highlight.inArray(date.toString())){
						td.className = "highlight";
						td.calendar = this;
						td.date = date.toString();
						td.onclick = function (){
							if (this.calendar.options.onpick){
								this.calendar.options.onpick(this.calendar,this.date);
							}
						};
					}
					td.appendChild(document.createTextNode(date.getDate()));
					date.setDate(date.getDate()+1);
				}
				tr.appendChild(td);
			}
			tbody.appendChild(tr);
		}
		// Create the table
		var table = document.createElement("TABLE");
		table.appendChild(caption);
		table.appendChild(thead);
		table.appendChild(tbody);
		// Replace the content of the view with the table
		var view = this.container.getElementsByTagName("DIV")[0];
		while (view.firstChild) view.removeChild(view.firstChild);  
		view.appendChild(table);
		// Update month and year pickers
		var pickers = this.container.getElementsByTagName("SELECT");
		pickers[0].selectedIndex = this.options.currentDate.getMonth();
		pickers[1].selectedIndex = this.options.currentDate.getFullYear()-this.options.startDate.getFullYear();
		
	}

	// Change current month or year
	this.setMonth = function (month){
		this.options.currentDate.setMonth(month);
		this.update();
	}
	this.setYear = function (year){
		this.options.currentDate.setYear(year);
		this.update();
	}
	this.previousMonth = function (){
		this.options.currentDate.setMonth(this.options.currentDate.getMonth()-1);
		if (this.options.currentDate.getTime()<this.options.startDate.getTime()){
			this.nextMonth();
		}
		this.update();
	}
	this.nextMonth = function(){
		this.options.currentDate.setMonth(this.options.currentDate.getMonth()+1);
		if (this.options.currentDate.getTime()>this.options.endDate.getTime()){
			this.previousMonth();
		}
		this.update();
	}
	
	// Generate and update the calendar
	this.generate();
}

// Open a calendar to pick a date and close it
var DatePicker = function (field,event){
	DatePicker.field = field;
	if (!this.calendar){
		this.calendar = new Calendar({
			onpick : function (_calendar,_date){
				if (DatePicker.field){
					DatePicker.field.value = _date;
					_calendar.container.style.display = "none";
				}
			}
		});
	}else{
		this.calendar.container.style.display = (this.calendar.container.style.display=="block")?"none":"block";
	}
	if (event){
		x = (navigator.appName.substring(0,3) == "Net") ? event.pageX : event.clientX + document.documentElement.scrollLeft;
		y = (navigator.appName.substring(0,3) == "Net") ? event.pageY+8 : event.clientY + document.documentElement.scrollTop;
		this.calendar.container.style.position = "absolute";
		this.calendar.container.style.left = x + "px";
		this.calendar.container.style.top = y + "px";
	}
}