/**
 * This datetime picker was written by Chris Johnson
 * All rights reserved
 * You may modify, distribute, and even profit from my code, as long as this header stays in tact
 */


//Initialize some globally accessible variables
var gTodayObj = new Date();
var gCurrentFullYear = gTodayObj.getFullYear();
var gCurrentMonth = gTodayObj.getMonth();
var gCurrentDate = gTodayObj.getDate();
var gCurrentHours = gTodayObj.getHours();
var gCurrentMinutes = gTodayObj.getMinutes();
var gMonths = new Array("Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
var gDaysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
//A leap year, so there's 29 days in February
if((gCurrentFullYear % 4 == 0) && (gCurrentFullYear % 100 != 0) || (gCurrentFullYear % 400 == 0)){
	gDaysInMonth[1] = 29;
}
var gDaysOfWeek = new Array("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi");

var gPoppedUp = false;
var gSelectedTimeField = false;
var gPopupDiv = false;
var gCalendarDiv = false;
var gCalendarLabelDiv = false;
var gTimeDiv = false;
var gChooseButton = false;
var gCloseButton = false;
var gSelectHour = false;
var gSelectMinute = false;
var gSelectedMonth = false;
var gSelectedYear = false;
var gSelectedDate = false;
var gSelectedDateObj = false;

var gDateFormat = false;
var gTimeFormat = false;
var gDateTimeFormat = false;
var gLinkedDays = false;
var gLinkedDates = false;
var gUnlinkedDays = false;
var gUnlinkedDates = false;
var gStartDate = false;
var gEndDate = false;
var gEndDate0Hour = false;
var gStartDate0Hour = false;

var dateTimePicker = function(){
	//this.date_format = "%Y-%m-%d";
	this.date_format = "%d-%m-%Y";
	this.time_format = "%h:%i";
	this.datetime_format = "%d %t";
	this.linked_days = new Array(0, 1, 2, 3, 4, 5, 6);
	this.linked_dates = new Array();
	this.unlinked_days = new Array();
	this.unlinked_dates = new Array();
	this.start_date = "";
	this.end_date = "";

	this.init = function(){
		var allElements = document.getElementsByTagName("*");
		for(var x = 0; x < allElements.length; x++){
			currentRel = allElements[x].getAttribute("rel");
			if(currentRel=="date"){
				allElements[x].onfocus = function(){
					showPicker(this, true, false);
				};
			}
			if(currentRel=="datetime"){
				allElements[x].onfocus = function(){
					showPicker(this, true, true);
				};
			}
			if(currentRel=="time"){
				allElements[x].onfocus = function(){
					showPicker(this, false, true);
				};
			}
		}
		gDateFormat = this.date_format;
		gTimeFormat = this.time_format;
		gDateTimeFormat = this.datetime_format;
		gLinkedDays = this.linked_days;
		gLinkedDates = this.linked_dates;
		gStartDate = this.start_date;
		gEndDate = this.end_date;
		if(this.start_date != ""){
			startParts = this.start_date.split("-");
			gStartDate0Hour = new Date(startParts[0], (parseInt(startParts[1], 10) - 1), startParts[2]);
			gStartDate0Hour.setHours(0);
			gStartDate0Hour.setMinutes(0);
			gStartDate0Hour.setSeconds(0);
			gStartDate0Hour.setMilliseconds(0);
		}
		if(this.end_date != ""){
			endParts = this.end_date.split("-");
			gEndDate0Hour = new Date(endParts[0], (parseInt(endParts[1], 10) - 1), endParts[2]);
			gEndDate0Hour.setHours(0);
			gEndDate0Hour.setMinutes(0);
			gEndDate0Hour.setSeconds(0);
			gEndDate0Hour.setMilliseconds(0);
		}
	};
};

function showPicker(fieldObj, showDateSelector, showTimeSelector){
	if(gPoppedUp==false){
		gSelectedTimeField = fieldObj;

		popupWidth = 190;
		if(showDateSelector){
			popupWidth += 30;
		}

		offsetTop = 0;
		offsetLeft = 0;
		obj = fieldObj;
		while(obj.offsetParent != undefined){
			offsetTop += parseInt(obj.offsetTop, 10);
			offsetLeft += parseInt(obj.offsetLeft, 10);
			obj = obj.offsetParent;
		}
		popupTop = offsetTop + 5;
		popupLeft = offsetLeft + 5;

		gPopupDiv = document.createElement("div");
		gPopupDiv.style.position = "absolute";
		gPopupDiv.style.top = popupTop + "px";
		gPopupDiv.style.left = popupLeft + "px";
		gPopupDiv.style.padding = "10px";
		gPopupDiv.className = "popupBox";

		if(showDateSelector){
			gCalendarDiv = document.createElement("div");
			gPopupDiv.appendChild(gCalendarDiv);

			gCalendarLabelDiv = document.createElement("div");
			gCalendarLabelDiv.className = "calendarDateLabel";
			gPopupDiv.appendChild(gCalendarLabelDiv);

			buildCalendar(null, null);
		}

		if(showTimeSelector){
			gTimeDiv = document.createElement("div");
			gPopupDiv.appendChild(gTimeDiv);

			buildTimeSelector();
		}
		
		if(gSelectedTimeField.getAttribute('rel')!="date") {
			gChooseButton = document.createElement("button");
			gChooseButton.innerHTML = "Ok";
			gChooseButton.onclick = function(){
				chooseDateTime();
			};
			gPopupDiv.appendChild(gChooseButton);
	
			gCloseButton = document.createElement("button");
			gCloseButton.innerHTML = "Fermer";
			gCloseButton.onclick = function(){
				closePopup();
			};
			gPopupDiv.appendChild(gCloseButton);
		}
		gPoppedUp = true;
		document.body.appendChild(gPopupDiv);
	}else{
		if(fieldObj!=gSelectedTimeField){
			alert("Ferme l'autre fenêtre du calendrier avant d'en ouvrir une nouvelle.");
			gSelectedTimeField.focus();
		}
	}
}

function buildCalendar(workingMonth, workingYear){
	if(workingMonth==null || workingYear==null){
		workingMonth = gCurrentMonth;
		workingYear = gCurrentFullYear;
	}

	if((workingYear % 4 == 0) && (workingYear % 100 != 0) || (workingYear % 400 == 0)){
		gDaysInMonth[1] = 29;
	}else{
		gDaysInMonth[1] = 28;
	}

	gCalendarDiv.innerHTML = "";
	var calendarTable = document.createElement("table");
	calendarTable.cellSpacing = "1";
	calendarTable.className = "calendar";

	var calendarTbody = document.createElement("tbody");
	var calendarThead = document.createElement("thead");

	var calendarCaption = document.createElement("div");
	calendarCaption.style.textAlign = "center";
	var spanPrev = document.createElement("span");
	var spanTitle = document.createElement("span");
	var spanNext = document.createElement("span");

	spanPrev.innerHTML = "&laquo;";
	spanPrev.className = "previous";
	var prevMonthDate = new Date(workingYear, workingMonth - 1, 1);
	spanPrev.onclick = function(){
		buildCalendar(prevMonthDate.getMonth(), prevMonthDate.getFullYear());
	};

	spanNext.innerHTML = "&raquo;";
	spanNext.className = "next";
	var nextMonthDate = new Date(workingYear, workingMonth + 1, 1);
	spanNext.onclick = function(){
		buildCalendar(nextMonthDate.getMonth(), nextMonthDate.getFullYear());
	};

	spanTitle.innerHTML = gMonths[workingMonth] + " " + workingYear;

	calendarCaption.appendChild(spanPrev);
	calendarCaption.appendChild(spanTitle);
	calendarCaption.appendChild(spanNext);

	gCalendarDiv.appendChild(calendarCaption);

	var today0Hour = new Date(gCurrentFullYear, gCurrentMonth, gCurrentDate);
	today0Hour.setHours(0);
	today0Hour.setMinutes(0);
	today0Hour.setSeconds(0);
	today0Hour.setMilliseconds(0);

	var firstOfMonth = new Date(workingYear, workingMonth, 1);
	var firstDayOfMonth = firstOfMonth.getDay();

	var workingDate = 0;
	var workingWeek = 0;
	var endOfMonth = false;
	var calendarWeek = false;
	var calendarDay = false;
	while(workingDate <= gDaysInMonth[workingMonth]){
		calendarWeek = document.createElement("tr");

		for(var x = 0; x <= 6; x++){
			if(workingWeek==0 && workingDate==0){
				if(firstDayOfMonth == x){
					workingDate++;
				}
			}
			calendarDay = document.createElement("td");
			if(workingDate==0 || workingDate > gDaysInMonth[workingMonth]){
				calendarDay.innerHTML = "&nbsp;";
				calendarDay.className += " paddingDate";
				calendarDay.title = "";
			}else{
				calendarDay.innerHTML = workingDate;

				working0Hour = new Date(workingYear, workingMonth, workingDate);
				working0Hour.setHours(0);
				working0Hour.setMinutes(0);
				working0Hour.setSeconds(0);
				working0Hour.setMilliseconds(0);

				calendarDay.className = gDaysOfWeek[x];

				if(working0Hour.getTime() < today0Hour.getTime()){
					calendarDay.className += " pastDate";
				}
				if(working0Hour.getTime() == today0Hour.getTime()){
					calendarDay.className += " presentDate";
				}
				if(working0Hour.getTime() > today0Hour.getTime()){
					calendarDay.className += " futureDate";
				}

				if(workingDate == gSelectedDate && workingMonth == gSelectedMonth && workingYear == gSelectedYear){
					chooseDate(workingYear, workingMonth, workingDate, calendarDay);
				}

				calendarDay.title = gDaysOfWeek[x] + ", " + workingDate + " " + gMonths[workingMonth] + " " + workingYear;

				canBeLinked = false;
				for(var j = 0; j < gLinkedDays.length; j++){
					if(x==gLinkedDays[j]){
						canBeLinked = true;
					}
				}
				for(var j = 0; j < gLinkedDates.length; j++){
					if((workingYear + "-" + padWithZeroes(parseInt(workingMonth, 10) + 1) + "-" + padWithZeroes(workingDate))==gLinkedDates[j] || (workingYear + "-" + (workingMonth + 1) + "-" + workingDate)==gLinkedDates[j]){
						canBeLinked = true;
					}
				}
				for(var j = 0; j < gUnlinkedDays.length; j++){
					if(workingDay == gUnlinkedDays[j]){
						canBeLinked = false;
					}
				}
				for(var j = 0; j < gUnlinkedDates.length; j++){
					if((workingYear + "-" + padWithZeroes(parseInt(workingMonth, 10) + 1) + "-" + padWithZeroes(workingDate))==gUnlinkedDates[j] || (workingYear + "-" + (workingMonth + 1) + "-" + workingDate)==gUnlinkedDates[j]){
						canBeLinked = false;
					}
				}
				if(gStartDate != false){
					if(gStartDate0Hour.getTime() > working0Hour.getTime()){
						canBeLinked = false;
					}
				}
				if(gEndDate != false){
					if(gEndDate0Hour.getTime() < working0Hour.getTime()){
						canBeLinked = false;
					}
				}

				if(canBeLinked){
					//calendarDay.onclick = (function(workingYearObj, workingMonthObj, workingDateObj) { return function(){chooseDate(workingYearObj, workingMonthObj, workingDateObj, this);}; })(workingYear, workingMonth, workingDate);
					calendarDay.onmousedown = (function(workingYearObj, workingMonthObj, workingDateObj) { return function(){chooseDate(workingYearObj, workingMonthObj, workingDateObj, this);if(gSelectedTimeField.getAttribute('rel')=="date"){chooseDateTime();}}; })(workingYear, workingMonth, workingDate);
					//calendarDay.onmouseup= function(){closePopup();};
					calendarDay.className += " selectableDay";

					//The selector has just been opened, select today
					if(gSelectedDate == false && gSelectedMonth == false && gSelectedYear == false){
						if(workingDate == gCurrentDate && workingMonth == gCurrentMonth && workingYear == gCurrentFullYear){
							var chooseToday = (function(workingYearObj, workingMonthObj, workingDateObj, calendarDayObj) {
								return(	function(){
									chooseDate(workingYearObj, workingMonthObj, workingDateObj, calendarDayObj);
								});
							})(workingYear, workingMonth, workingDate, calendarDay);
							chooseToday();
						}
					}
				}else{
					calendarDay.className += " unselectableDay";
				}

				workingDate++;
			}
			calendarWeek.appendChild(calendarDay);
		}

		calendarTbody.appendChild(calendarWeek);

		workingWeek++;
	}

	calendarTable.appendChild(calendarThead);
	calendarTable.appendChild(calendarTbody);
	gCalendarDiv.appendChild(calendarTable);
}

function buildTimeSelector(){
	gTimeDiv.innerHTML = "";
	var label = document.createTextNode("Heure: ");
	gTimeDiv.appendChild(label);
	gSelectHour = document.createElement("select");
	gSelectMinute = document.createElement("select");
	var option = false;

	for(var x = 0; x <= 23; x++){
		option = document.createElement("option");
		option.value = padWithZeroes(x);
		option.innerHTML = padWithZeroes(x);
		if(parseInt(gCurrentHours, 10) == parseInt(x, 10)){
			option.selected = "true";
		}
		gSelectHour.appendChild(option);
	}

	for(var x = 0; x <= 59; x+=5){
		option = document.createElement("option");
		option.value = padWithZeroes(x);
		option.innerHTML = padWithZeroes(x);
		if(Math.floor((parseInt(gCurrentMinutes, 10)+5)/10)*10 == parseInt(x, 10)){
			option.selected = "true";
		}
		gSelectMinute.appendChild(option);
	}

	var label = document.createTextNode(":");

	gTimeDiv.appendChild(gSelectHour);
	gTimeDiv.appendChild(label);
	gTimeDiv.appendChild(gSelectMinute);
}

function chooseDate(year, month, date, selectObj){
	if(gSelectedDateObj){
		gSelectedDateObj.className = gSelectedDateObj.className.replace("selected", "");
	}
	gSelectedDateObj = selectObj;
	gSelectedDateObj.className += " selected";
	gSelectedMonth = padWithZeroes(month);
	gSelectedYear = year;
	gSelectedDate = padWithZeroes(date);
	gCalendarLabelDiv.innerHTML = date + " " + gMonths[month] + " " + year;
	
	



}

function chooseDateTime(){
	var dateTimeText = "";
	var dateText = "";
	var timeText = "";
	//if(gSelectedDate != false && gSelectedMonth != false && gSelectedYear != false){
	// !! bug si gSelectedMonth janvier (00) == false !!!!
	if(gSelectedDate != false && gSelectedYear != false){
		dateText = gDateFormat;
		dateText = dateText.replace("%Y", gSelectedYear);
		dateText = dateText.replace("%y", String(gSelectedYear).substring(2));
		dateText = dateText.replace("%m", padWithZeroes(parseInt(gSelectedMonth, 10) + 1));
		dateText = dateText.replace("%M", parseInt(gSelectedMonth, 10) + 1);
		dateText = dateText.replace("%D", parseInt(gSelectedDate, 10));
		dateText = dateText.replace("%d", padWithZeroes(gSelectedDate));
		var selectedDateObject = new Date(gSelectedYear, gSelectedMonth, gSelectedDate);
	}
	if(gSelectHour != false && gSelectMinute != false){
		timeText += gTimeFormat;
		if(selectedDateObject){
			selectedDateObject.setHours(gSelectHour.options[gSelectHour.selectedIndex].value);
			selectedDateObject.setMinutes(gSelectMinute.options[gSelectMinute.selectedIndex].value);
			selectedDateObject.setSeconds(0);
			selectedDateObject.setMilliseconds(0);
		}
		timeText = timeText.replace("%H", padWithZeroes(gSelectHour.options[gSelectHour.selectedIndex].value));
		//timeText = timeText.replace("%h", padWithZeroes(conv24to12(gSelectHour.options[gSelectHour.selectedIndex].value)));
		timeText = timeText.replace("%h", padWithZeroes((gSelectHour.options[gSelectHour.selectedIndex].value)));
		timeText = timeText.replace("%i", padWithZeroes(gSelectMinute.options[gSelectMinute.selectedIndex].value));
		timeText = timeText.replace("%a", (gSelectHour.options[gSelectHour.selectedIndex].value < 12 ? "am" : "pm"));
		timeText = timeText.replace("%A", (gSelectHour.options[gSelectHour.selectedIndex].value < 12 ? "AM" : "PM"));
	}
	if(selectedDateObject){
		timestamp = selectedDateObject.getTime() / 1000;
	}else{
		timestamp = 0;
	}
	dateTimeText = gDateTimeFormat;
	dateTimeText = dateTimeText.replace("%d", dateText);
	dateTimeText = dateTimeText.replace("%t", timeText);
	dateTimeText = dateTimeText.replace("%s", timestamp);
	gSelectedTimeField.value = dateTimeText;
	gSelectedTimeField.focus();
	gSelectedTimeField.blur();
	closePopup();
	
}

function closePopup(){
	//Clean up
	gPopupDiv.innerHTML = "";
	gPopupDiv.parentNode.removeChild(gPopupDiv);
	gPoppedUp = false;
	gSelectedTimeField = false;
	gPopupDiv = false;
	gCalendarDiv = false;
	gCalendarLabelDiv = false;
	gTimeDiv = false;
	gChooseButton = false;
	gCloseButton = false;
	gSelectHour = false;
	gSelectMinute = false;
	gSelectedMonth = false;
	gSelectedYear = false;
	gSelectedDate = false;
	gSelectedDateObj = false;
}



function padWithZeroes(number){
	var newNumber = parseInt(number, 10);
	if(newNumber < 10){
		newNumber = "0" + newNumber;
	}
	return(newNumber);
}

function conv24to12(hours){
	hours = parseInt(hours, 10);
	if(hours > 12){
		hours -= 12;
	}
	if(hours==0){
		hours = 12;
	}
	return(hours);
}