var calendar_currentMonth = null; 
var calendar_currentYear = null; 
var calendar_element = null; 
var calendar_highlightDay = null; 
var calendar_highlightMonth = null; 
var calendar_highlightYear = null; 
var calendar_target = null; 
var calendar_target2 = null; 
var calendar_selectDay = null;
var calendar_inside = null;
var calendar_hideable = null;
var calendar_selectDayCallback = null;

/* Month names, maybe changed for translation.
 */
var calendar_monthNames = new Array(
	'January', 'February', 'March', 
	'April', 'May', 'June', 
	'July', 'August', 'September', 
	'October', 'November', 'December'
);

/* Day names, maybe changed for translation.
 */
var calendar_dayNames = new Array(
	'M', 'T', 'W', 'T', 'F', 'S', 'S'
);

/* Return the number of days in the month.
 * The month have to be in the range 1 to 12.
 */
function calendar_getNbDays(month, year){
  if( (month==1) || (month==3) || (month==5) || 
      (month==7) || (month==8) || (month==10) ||
      (month==12) )
    return 31;
  if(month==2) {
    if(((year%4) == 0) && 
       (((year % 100)!=0) || ((year % 400) == 0)))
      return 29;
    return 28;
  }
  return 30;
}

/* Return the first day of the month (range: 0-7)
 * The month have to be in the range 1 to 12.
 * Year is expected to be after 1970.
 */
function calendar_getFirstDay(month, year){	
  var date = new Date(year, month-1, 1, 0, 0, 0);
  var epoch = new Date(1970, 0, 1, 0, 0, 0);
  var diff = Math.ceil((date - epoch)/86400000);
	var dayName = ((diff%7)+3)%7;
	return dayName;
}

/* Return a html string ready to display a calendar 
 * for the given month.
 * The month have to be in the range 1 to 12.
 * The hiday is a day to highlight (bold) or 0 if none
 */
function calendar_displayMonth(month, year){
	var result = "<table class='calendarSheet'>";
	var day = 1;
	var start = calendar_getFirstDay(month, year);
	var end = start + calendar_getNbDays(month, year);
	var i=0;

	var hiday = 0;
	if((month==calendar_highlightMonth)&&(year==calendar_highlightYear)){
		hiday = calendar_highlightDay;
	}
	
	result+="<tr class='calendarSheetDays'>";
	for( i=0; i<calendar_dayNames.length; i++ ){
		result+='<td>';
		if(i==6){
			result+='<span class="calendarSheetSunday">'+calendar_dayNames[i]+'</span>';
		} else {
			result+=calendar_dayNames[i];
		}
		result+='</td>';		
	}
	result+="</tr>";
	
	i=0;
	while((i<end)||((i%7)!=0)){
		if((i%7)==0) result+="<tr class='calendarSheet'>";
		if((i<start)||(i>=end)){
			result+="<td>&nbsp;</td>";
		} else {
			if(day<10) daystr = '&nbsp;'+day;
			else daystr = day;
			if(hiday==day){
				style=" class='calendarSheetHighlight'";
			} else {
				style=" class='calendarSheet'";
			}
			
			result+="<td class='calendarSheet' "+
								"onmouseover='calendar_highlight(this, \"calendarSheet\"); return calendar_setDayStatus("+day+","+month+","+year+");' "+
				        "onmouseout='calendar_unhighlight(this, \"calendarSheet\"); calendar_setBlankStatus();' "+
							"><a href='#'"+style+" "+
			        	"onclick='javascript: return calendar_selectDay("+day+");'"+
			        ">"+daystr+
				      "</a></td>";			
			day++;
		}
		if((i%7)==6) result+="</tr>";
		i++;
	}
		
	result+="</table>";
	return result;
}

/* Utility function to unhighlight a html element using CSS
 */
function calendar_unhighlight(cell, prefix){
	if(prefix==null) prefix='';
	cell.className = prefix+'';
}

/* Utility function to highlight a html element using CSS
 */
function calendar_highlight(cell, prefix){
	if(prefix==null) prefix='';
	cell.className = prefix+'Selected';
}

/* Called when entering the calendar zone
 */
function calendar_enter(){		
	calendar_inside = true;
}

/* Called when leaving the calendar zone
 */
function calendar_leave(){
	calendar_inside = false;
	if(calendar_hideable)
		window.setTimeout("calendar_hide()", 1000);
}

/* Calendar hide mechanism
 */
function calendar_hide(){
	if(!calendar_inside){
		if(calendar_element!=null){
			calendar_element.innerHTML= '';
			calendar_element.className = 'calendarHidden';
      window.status="";
    }
		calendar_target = null;		
	}
}

/* Refresh the current calendar display.
 */
function calendar_refresh(){
	calendar_element.innerHTML = calendar_generate(
			calendar_currentMonth,
			calendar_currentYear
	);
}

/* Forward one year
 */
function calendar_forwardYear(){
	calendar_currentYear++;
	calendar_refresh();
	return false;
}

/* Rewind one year
 */
function calendar_rewindYear(){
	calendar_currentYear--;
	if(calendar_currentYear < 1970) calendar_currentYear = 1970;
	calendar_refresh();
	return false;
}

/* Forward one month
 */
function calendar_forwardMonth(){
	calendar_currentMonth++;
	if(calendar_currentMonth>12){
		calendar_currentMonth = 1;
		calendar_currentYear++;
	}
	calendar_refresh();
	return false;
}

/* Rewind one month
 */
function calendar_rewindMonth(){
	calendar_currentMonth--;
	if(calendar_currentMonth < 1){
		calendar_currentMonth = 12;
		calendar_currentYear--;
		if(calendar_currentYear < 1970) calendar_currentYear = 1970;
	}
	calendar_refresh();
	return false;
}

function calendar_setDayStatus(day, month, year){
	window.status=day+'/'+month+'/'+year;
	return true;
}

function calendar_setMonthStatus(month, year){
	window.status=calendar_monthNames[month-1]+' '+year;
	return true;
}

function calendar_setBlankStatus(){
  window.status="";
}

/* Generate the date selector
 */
function calendar_generate(month, year){
	var result="<table class='calendar'>";
	
	result+="<thead class='calendar'><tr>"+
	        "<td class='calendar' "+
            "onmouseout='calendar_unhighlight(this, \"calendar\"); calendar_setBlankStatus(); ' "+
	          "onmouseover='calendar_highlight(this, \"calendar\"); return calendar_setMonthStatus("+month+","+(year-1)+");' "+
            "onclick='javascript: return calendar_rewindYear();' "+
	        ">"+
	          "<a class='calendarLink' href='#' "+
	          "   onclick='javascript: return calendar_rewindYear();'>"+(year-1)+"</a>"+
	        "</td>"+
	        "<td class='calendar'>"+calendar_monthNames[month-1]+"&nbsp;"+year+"</td>"+
	        "<td class='calendar' "+
            "onmouseout='calendar_unhighlight(this, \"calendar\"); calendar_setBlankStatus();' "+
	          "onmouseover='calendar_highlight(this, \"calendar\"); return calendar_setMonthStatus("+month+","+(year+1)+");' "+
            "onclick='javascript: calendar_forwardYear();' "+
	        ">"+
	          "<a class='calendarLink' href='#' "+
	          "   onclick='javascript: return calendar_forwardYear();'>"+(year+1)+"</a>"+
	        "</td>"+
	        "</tr></thead>";

	var nextMonth = ((month+1)>12)? 1 : (month+1);	
	var prevMonth = ((month-1)<1)? 12 : (month-1);	
	result+="<tbody class='calendar'>"+
			"<tr>"+
	        "<td class='calendar' "+
            "onclick='javascript: return calendar_rewindMonth();' "+
	          "onmouseover='calendar_highlight(this, \"calendar\"); return calendar_setMonthStatus("+prevMonth+","+year+");' "+
            "onmouseout='calendar_unhighlight(this, \"calendar\"); calendar_setBlankStatus();' "+
	        ">"+
	          "<a class='calendarLink' href='#' onclick='javascript: return calendar_rewindMonth();'>"+calendar_monthNames[prevMonth-1].substr(0,3)+"</a>"+
	        "</td>"+
					"<td class='calendar'>"+calendar_displayMonth(month, year)+"</td>"+
	        "<td class='calendar' "+
	          "onmouseover='calendar_highlight(this, \"calendar\"); return calendar_setMonthStatus("+nextMonth+","+year+");' "+
            "onmouseout='calendar_unhighlight(this, \"calendar\"); calendar_setBlankStatus();' "+
            "onclick='javascript: return calendar_forwardMonth();' "+
	        ">"+
	          "<a class='calendarLink' href='#' onclick='javascript: return calendar_forwardMonth();'>"+calendar_monthNames[nextMonth-1].substr(0,3)+"</a>"+
	        "</td>"+
	        "</tr>";
	
	result+="</tbody></table>";
	
	return result;
}

function calendar_getObject(objname){
  if(document.getElementById)
    return document.getElementById(objname);
  else 
    return eval(objname);
}

function calendar_setDate(month, year){
	calendar_currentMonth = month;
	calendar_currentYear = year;
	if((calendar_currentMonth==null)||(calendar_currentYear==null)){
		var date = new Date();
		calendar_currentMonth = date.getMonth()+1;
		calendar_currentYear = date.getFullYear();
	}
}


/*************************************************************************************/
/************************DEFAULT BEHAVIOUR********************************************/
/*************************************************************************************/

/* Function called when a day is selected
 */
function calendar_selectDayDefault(day){
	alert(
		day+"/"+
		calendar_currentMonth+"/"+
		calendar_currentYear
	);
  window.status="";
	if(calendar_selectDayCallback!=null) calendar_selectDayCallback();
	return false;
}

/* Display a calendar selector
 */
function calendar_display(element, day, month, year){
	var date = new Date();
	calendar_highlightDay = date.getDate(); 
	calendar_highlightMonth = date.getMonth()+1; 
	calendar_highlightYear = date.getFullYear(); 
	
	calendar_setDate(month, year);

	calendar_element = element;
	calendar_target = null;

	calendar_element.innerHTML = calendar_generate(calendar_currentMonth, calendar_currentYear);
	calendar_selectDay = calendar_selectDayDefault;
	calendar_hideable = false;
}


/*************************************************************************************/
/************************BUTTON SELECTOR BEHAVIOUR************************************/
/*************************************************************************************/

/* Get an object absolute x position */
function calendar_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;
}

/* Get an object absolute y position */
function calendar_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 calendar_getFrameWidth(){
  var width = -1;
  if (window.innerWidth)
    width = window.innerWidth;
  else if((document.documentElement) && 
          (document.documentElement.clientWidth))
    width = document.documentElement.clientWidth;
  else if (document.body)
    width = document.body.clientWidth;
  return width;
}

function calendar_getFrameOffsetX(){
  var offset = -1;
  if (window.pageXOffset)
    offset = window.pageXOffset;
  else if ((document.documentElement) && 
           (document.documentElement.scrollTop))
    offset = document.documentElement.scrollLeft;
  else if (document.body)
    offset = document.body.scrollLeft;
  if(!(offset>=0)) offset = 0;
  return offset;
}

function calendar_getPopupPosX(refElement, popupDiv){
  var posX = calendar_findPosX(refElement);	
  
  var width = calendar_getFrameWidth();
  if(width<=0) return posX;
  var offset = calendar_getFrameOffsetX();
  
  var maxX = width+offset;
      
	if((popupDiv.offsetWidth+posX) > maxX)
		posX = maxX-popupDiv.offsetWidth-2;
  return posX;
}

/* Function called when a day is selected
 */
function calendar_selectDayButton(day){
	if(day<10) dayStr = "0"+day;
	else dayStr = day;
	if(calendar_currentMonth<10) monthStr = "0"+calendar_currentMonth;
	else monthStr = calendar_currentMonth;
	
	calendar_target.value = 
		dayStr+"/"+
		monthStr+"/"+
		calendar_currentYear;
	calendar_element.innerHTML= '';
	calendar_element.className = 'calendarHidden';
	calendar_target = null; 
	if(calendar_selectDayCallback!=null) calendar_selectDayCallback();
	return false;
}

/* Display a calendar selector with the given button as target
 */
function calendar_displayButton(button, divName){
	calendar_element = calendar_getObject(divName);
	if(calendar_target != null){
		calendar_element.innerHTML= '';
		calendar_element.className = 'calendarHidden';
		calendar_target = null;
		return;
	}

	var dateArray=button.value.split("/");
	if(dateArray.length!=3){
		var date = new Date();
		var day = date.getDate();
		var month = date.getMonth()+1; 
		var year = date.getFullYear();
	} else {
		var day = Number(dateArray[0]);
		var month = Number(dateArray[1]);
		var year = Number(dateArray[2]);
	}
	var day = Number(dateArray[0]);
	var month = Number(dateArray[1]);
	var year = Number(dateArray[2]);
	calendar_highlightDay = day; 
	calendar_highlightMonth = month; 
	calendar_highlightYear = year; 
	
	calendar_setDate(month, year);

	calendar_target = button;

	calendar_element.innerHTML = calendar_generate(calendar_currentMonth, calendar_currentYear);	
	calendar_element.className = 'calendarVisible';
	calendar_element.style.left = calendar_getPopupPosX(button, calendar_element);
  calendar_element.style.width = calendar_element.offsetWidth;
	calendar_element.style.top = calendar_findPosY(button)+button.offsetHeight;
	calendar_selectDay = calendar_selectDayButton;
	calendar_hideable = true;
}

/*************************************************************************************/
/************************TEXTAREA SELECTOR BEHAVIOUR**********************************/
/*************************************************************************************/

/* Function called to change the textarea content
 */
function calendar_setDayTextArea(day, month, year){
	if(day<10) dayStr = "0"+day;
	else dayStr = day;
	if(month<10) monthStr = "0"+month;
	else monthStr = month;
	
	calendar_target.value = 
		dayStr+"/"+
		monthStr+"/"+
		year;
}

/* Function called when a day is selected
 */
function calendar_selectDayTextArea(day){
	calendar_setDayTextArea(day, calendar_currentMonth, calendar_currentYear );
	calendar_element.innerHTML= '';
	calendar_element.className = 'calendarHidden';
	calendar_target = null; 
	if(calendar_selectDayCallback!=null) calendar_selectDayCallback();
	return false;
}

/* Display a calendar selector with the given textarea as target
 */
function calendar_displayTextArea(textarea, divName, ref){
	calendar_element = calendar_getObject(divName);
	if(calendar_target != null){
		calendar_element.innerHTML= '';
		calendar_element.className = 'calendarHidden';
		calendar_target = null;
		return;
	}

	calendar_target = textarea;

	var dateArray=calendar_target.value.split("/");
	if(dateArray.length!=3){
		var date = new Date();
		var day = date.getDate();
		var month = date.getMonth()+1; 
		var year = date.getFullYear();
		//calendar_setDayTextArea(day, month, year);
	} else {
		var day = Number(dateArray[0]);
		var month = Number(dateArray[1]);
		var year = Number(dateArray[2]);
	}
	calendar_highlightDay = day; 
	calendar_highlightMonth = month; 
	calendar_highlightYear = year; 
	
	calendar_setDate(month, year);

  calendar_element.innerHTML = "";
  calendar_element.style.left = calendar_getFrameOffsetX();
  calendar_element.style.top = 0;
  calendar_element.innerHTML = calendar_generate(calendar_currentMonth, calendar_currentYear);
	calendar_element.className = 'calendarVisible';

	calendar_element.style.left = calendar_getPopupPosX(textarea, calendar_element);
  calendar_element.style.width = calendar_element.offsetWidth;
	calendar_element.style.top = calendar_findPosY(textarea)+textarea.offsetHeight;
	calendar_selectDay = calendar_selectDayTextArea;
	calendar_hideable = false;
}

/*************************************************************************************/
/****************************TEXT SELECTOR BEHAVIOUR**********************************/
/*************************************************************************************/

/* Function called to change the textarea content
 */
function calendar_setDayText(day, month, year){
	if(day<10) dayStr = "0"+day;
	else dayStr = day;
	if(month<10) monthStr = "0"+month;
	else monthStr = month;


	calendar_target.innerHTML= 
		dayStr+"/"+
		monthStr+"/"+
		year;
	calendar_target2.value = 
		dayStr+"/"+
		monthStr+"/"+
		year;
}

/* Function called when a day is selected
 */
function calendar_selectDayText(day){
	calendar_setDayText(day, calendar_currentMonth, calendar_currentYear );
	calendar_element.innerHTML= '';
	calendar_element.className = 'calendarHidden';
	calendar_target = null; 
	if(calendar_selectDayCallback!=null) calendar_selectDayCallback();
	return false;
}

/* Display a calendar selector with the given select as target
 */
function calendar_displayText(textzone, hidden, divName){
	calendar_element = calendar_getObject(divName);
	if(calendar_target != null){
		calendar_element.innerHTML= '';
		calendar_element.className = 'calendarHidden';
		calendar_target = null;
		return;
	}

	calendar_target = calendar_getObject(textzone);
	calendar_target2 = hidden;

	var dateArray=calendar_target2.value.split("/");
	if(dateArray.length!=3){
		var date = new Date();
		var day = date.getDate();
		var month = date.getMonth()+1; 
		var year = date.getFullYear();
		calendar_setDayText(day, month, year);
	} else {
		var day = Number(dateArray[0]);
		var month = Number(dateArray[1]);
		var year = Number(dateArray[2]);
	}
	calendar_highlightDay = day; 
	calendar_highlightMonth = month; 
	calendar_highlightYear = year; 
	
	calendar_setDate(month, year);

	var ref = calendar_getObject(textzone+"_ref");
	calendar_element.onmouseover=calendar_enter;
	calendar_element.onmouseout=calendar_leave;	
	calendar_element.innerHTML = calendar_generate(calendar_currentMonth, calendar_currentYear);	
	calendar_element.className = 'calendarVisible';
	calendar_element.style.left = calendar_getPopupPosX(ref, calendar_element);
  calendar_element.style.width = calendar_element.offsetWidth;
	calendar_element.style.top = calendar_findPosY(ref)+ref.offsetHeight;
	calendar_selectDay = calendar_selectDayText;
	calendar_hideable = false;
	calendar_inside = true;
}

