// Globals
var lang = "en";
var startDay;
var nav4 = window.Event ? true : false;

// Days of the Week:
var Day = {
  en: new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat"),
  de: new Array("So","Mo","Di","Mi","Do","Fr","Sa"),
  sv: new Array("S\u00f6n","M\u00e5n","Tis","Ons","Tor","Fre","L\u00f6r")
}

// Names of the Months:
var Month = {
  en: new Array("January","February","March","April","May","June",
                "July","August","September","October","November","December"),
  de: new Array("Januar","Februar","März","April","Mai","Juni",
                "Juli","August","September","Oktober","November","Dezember"),
  sv: new Array("Januari","Februari","Mars","April","Maj","Juni",
                "Juli","Augusti","September","Oktober","November","December")
}

function setLanguage(language) {
  switch (language) {
    case "en": 
       lang = language;
       startDay = 0;
    break;
    case "de":
       lang = language;
       startDay = 0;
    break;
    case "sv":
       lang = language;
       startDay = 1;
    break;
    default:
       lang = "en";
       startDay = 0;
    break;
  }
}
function getTarget(e) {
   if (nav4) {
     return e.target;
   } else {
     return window.event.srcElement;
   }
}


function findCoords(e) {
/* works with IE 4+, NS4, NS6 and other Gecko, OmniWeb, Opera (4) 5+,
iCab, IceBrowser, Esape 4, HotJava 3, Konqueror and, as long as they
follow the standards, loads more */
   var posX = 0, posY = 0;
   if( !e ) { e = window.event; } if( !e ) { return [ 0, 0 ]; }
   if( typeof( e.pageX ) == 'number' ) {
      posX = e.pageX; posY = e.pageY;
   } else {
      if( typeof( e.clientX ) == 'number' ) {
         posX = e.clientX; posY = e.clientY;
         if( document.body && !( window.opera || window.debug || navigator.vendor == 'KDE' ) ) {
            if( typeof( document.body.scrollTop ) == 'number' ) {
               posX += document.body.scrollLeft; posY += document.body.scrollTop;
            }
         }
         if( document.documentElement && !( window.opera || window.debug || navigator.vendor == 'KDE' ) ) {
            if( typeof( document.documentElement.scrollTop ) == 'number' ) {
               posX += document.documentElement.scrollLeft; posY += document.documentElement.scrollTop;
            }
         }
      }
   }
   return [ posX, posY ];
}

function CalendarDate(y,m,d) {
   // Force the values to be int's
    this.year=parseInt(y,10);
    this.month=parseInt(m,10); // jan=1, feb=2,...
    this.day=parseInt(d,10);
// alert("CalendarDate:" + this.year + " " + this.month + " " + this.day);
}

function CalendarNextMonth (calendarObject) {
  calendarObject.month += 1;
  if(calendarObject.month>12){
    calendarObject.month = 1;
    calendarObject.year += 1;
    if( calendarObject.year==0 ) calendarObject.year = 1;
  }
}

function CalendarPreviousMonth (calendarObject) {
  calendarObject.month -= 1;
  if(calendarObject.month==0  ){
    calendarObject.month = 12;
    calendarObject.year -= 1;
    if( calendarObject.year==0 ) calendarObject.year = 1;
  }
}

var JulianDate = {

   // Gregorian Calendar adopted Oct. 15, 1582 (2299161)
   JGREG: 15 + 31*(10+12*1582),
   HALFSECOND: 0.5
}

function getMonth(i) {
  switch (lang) {
    case "en": return Month.en[i];
    case "de": return Month.de[i];
    case "sv": return Month.sv[i];
    default: return "";
  }
}

function getDay(i) {
  switch (lang) {
    case "en": return Day.en[i];
    case "de": return Day.de[i];
    case "sv": return Day.sv[i];
    default: return "";
  }
}

/**
* Returns the Julian day number that begins at noon of
* this day, Positive year signifies A.D., negative year B.C.
* Remember that the year after 1 B.C. was 1 A.D.
*
* ref :
*  Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
function toJulian(calDate) {
 // calDate is of type CalendarDate

 var year=calDate.year;
 var month=calDate.month; // jan=1, feb=2,...
 var day=calDate.day;

 var julianYear = year;
 if (year < 0) julianYear++;
 var julianMonth = month;
 if (month > 2) {
     julianMonth++;
 }
 else {
     julianYear--;
     julianMonth += 13;
 }

 var julian = (Math.floor(365.25 * julianYear)
   + Math.floor(30.6001*julianMonth) + day + 1720995.0);

 if (day + 31 * (month + 12 * year) >= JulianDate.JGREG) {
    // change over to Gregorian calendar
    var ja = Math.round(0.01 * julianYear);
    julian += 2 - ja + (0.25 * ja);
   }
   return Math.floor(julian);
}

/**
* Converts a Julian day to a calendar date
* ref :
* Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
function fromJulian(injulian) {

  var jalpha,ja,jb,jc,jd,je,year,month,day;
  var julian = injulian + JulianDate.HALFSECOND / 86400.0;

  ja = Math.round(injulian);
  if (ja>= JulianDate.JGREG) {    
     jalpha = Math.floor(((ja - 1867216) - 0.25) / 36524.25); 
     ja = ja + 1 + jalpha - Math.floor(jalpha / 4);
  }

  jb = ja + 1524;
  jc = Math.floor(6680.0 + ((jb - 2439870) - 122.1) / 365.25);
  jd = 365 * jc + Math.floor(jc / 4);
  je = Math.floor((jb - jd) / 30.6001);
  day = jb - jd - Math.floor(30.6001 * je);
  month = je - 1;

  if (month > 12) month = month - 12;
  year = jc - 4715;

  if (month > 2) year--;
  if (year <= 0) year--;
  return new CalendarDate(year, month, day);
}

//
// dayOfWeek()
//
// Argument: Julian day number;
// Return: Day of week;
//
function dayOfWeek( julian ){
	
	return (julian+1-startDay)%7;
	
}

function test() {
  // FIRST TEST reference point
  alert("Julian date for May 23, 1968 : "
    + toJulian( new CalendarDate(1968, 5, 23 ) ));
  // output : 2440000
  results = fromJulian(toJulian(new CalendarDate(1968, 5, 23)));
  alert("... back to calendar : " + results.year + " "
     + results.month + " " + results.day);

  // SECOND TEST today
  var today = new Date();
  var todayJulian = toJulian(
     new CalendarDate(today.getFullYear(), today.getMonth()+1, 
                      today.getDay()+1));
  alert("Julian date for today : " + todayJulian);
  results = fromJulian(todayJulian);
  alert("... back to calendar : " + results.year + " " + results.month 
       + " " + results.day);

  // THIRD TEST
  var date1 = toJulian(new CalendarDate(2005,1,1));
  var date2 = toJulian(new CalendarDate(2005,1,31));
  alert("Between 2005-01-01 and 2005-01-31 : "
    + (date2 - date1) + " days");
  /*
   expected output :

   Julian date for May 23, 1968 : 2440000.0
   ... back to calendar 1968 5 23
   Julian date for today : 2453487.0
   ... back to calendar 2005 4 26
   Between 2005-01-01 and 2005-01-31 : 30.0 days
  */
}

function createDaysRow (daysInAWeek) {
  var trDays = document.createElement("tr");
  var thDay, tdDay, txtDay;
  for(i=startDay;i<daysInAWeek+startDay;i++){
     thDay  = document.createElement("th");
     txtDay = document.createTextNode(getDay(i%7));
     thDay.appendChild(txtDay);
     trDays.appendChild(thDay);
  }
  return trDays;
}

function formatDate(y,m,d) {
   var res;
   res = y + "-";
   if (m < 10) {
     res += "0" + m + "-";
   } else {
     res += m + "-";
   }
   if (d < 10) {
     res += "0" + d;
   } else {
     res += d;
   }
   return res;
}

function findPosition(element) {
  if(element) {
    var x = element.offsetLeft;
    var y = element.offsetTop;
    var parent = findPosition(element.offsetParent);
    return [parent[0] + x, parent[1] + y];
  } else {
    return [0,0];
  }
}

function previousYear(e) {
var dateObject = document.getElementById(getTarget(e).dateObject);
var thisDate = dateObject.thisDate;
var inputTarget = dateObject.inputTarget;
document.body.removeChild(dateObject);
inputTarget.value=formatDate((thisDate.year-1), thisDate.month, thisDate.day);
inputTarget.onclick();
}
function previousMonth(e) {
var dateObject = document.getElementById(getTarget(e).dateObject);
var thisDate = dateObject.thisDate;
var inputTarget = dateObject.inputTarget;
document.body.removeChild(dateObject);
CalendarPreviousMonth(thisDate);
inputTarget.value=formatDate(thisDate.year, thisDate.month, thisDate.day);
inputTarget.onclick();
}
function nextYear(e) {
var dateObject = document.getElementById(getTarget(e).dateObject);
var thisDate = dateObject.thisDate;
var inputTarget = dateObject.inputTarget;
document.body.removeChild(dateObject);
inputTarget.value=formatDate((thisDate.year+1), thisDate.month, thisDate.day);
inputTarget.onclick();
}
function nextMonth(e) {
var dateObject = document.getElementById(getTarget(e).dateObject);
var thisDate = dateObject.thisDate;
var inputTarget = dateObject.inputTarget;
document.body.removeChild(dateObject);
CalendarNextMonth(thisDate);
inputTarget.value=formatDate(thisDate.year, thisDate.month, thisDate.day);
inputTarget.onclick();
}
function setDate(e) {
var target = getTarget(e);
var dateObject = document.getElementById(target.dateObject);
var day = target.day;
var thisDate = dateObject.thisDate;
var inputTarget = dateObject.inputTarget;
document.body.removeChild(dateObject);
inputTarget.value=formatDate(thisDate.year, thisDate.month, day);
}


//
// generateCalendar()
//
// Arguments: Year, Month, Day, and the ID of the target element.
//
// This function creates the popup calendar.  Clicking on a date
// populates the target element with the chosen date in ISO 8601
// YYYY-MM-DD format (for Common Era years: years before Common Era
// are prefixed with a negative sign) and closes the popup window.
//
function generateCalendar( Y, M, D, targetId ){
	
	
	var daysInMonth = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	var daysInAWeek=7;
	var OutputString;
	
	// Guard against arguments that are really passed as strings:
	// Get year:
	var today = new Date();
	if( Y=="" || isNaN(Y) ){
		thisYear=today.getFullYear();
	}else{
		thisYear=parseInt(Y,10);
	}
	// Get month:
	if( M=="" || isNaN(M) ){
		thisMonth=today.getMonth()+1;
	}else{
		thisMonth=parseInt(M,10);
		if(thisMonth<1) thisMonth=1;
		if(thisMonth>12) thisMonth=12;
	}
	// Get day:
	if( D=="" || isNaN(D) ){
		thisDay=today.getDate();
	}else{
		thisDay=parseInt(D,10);
		if(thisDay<0) thisDay=1;
		if(thisDay>31) thisDay=31;
	}
	
	// Calculate the number of days in February:
	if ((thisYear % 4) == 0){
		daysInMonth[ 1 ] = 29;
		if((thisYear % 100) == 0 && (thisYear % 400) != 0){
			daysInMonth[ 1 ] = 28;
		}
	}
	
	
	// Start the calendar table with day headings:
           var tab = document.createElement("table");
           tab.id=targetId
           tab.thisDate= new CalendarDate(thisYear, thisMonth, thisDay);
           tab.border="1";
           tab.className="calendar";
           var tb = document.createElement("tbody");
           tab.appendChild(tb);
           var tr = document.createElement("tr");
           tr.className = "calendarheading";
           tb.appendChild(tr);
           var tdLeftLeft = document.createElement("td");
           tdLeftLeft.onclick = previousYear;
           tdLeftLeft.dateObject = targetId;
           var yearBack = document.createTextNode("<<");
           tdLeftLeft.appendChild(yearBack);
           tdLeftLeft.className = "calendarNavigate";
           tr.appendChild(tdLeftLeft);
           var tdLeft = document.createElement("td");
           tdLeft.onclick = previousMonth;
           tdLeft.dateObject = targetId;
           var monthBack = document.createTextNode("<");
           tdLeft.appendChild(monthBack);
           tdLeft.className = "calendarNavigate";
           tr.appendChild(tdLeft);
	// Print the month heading:
           var tdMonth = document.createElement("td");
           tdMonth.className = "calendarheading";
           tdMonth.colSpan = "3";
           var txtMonth = document.createTextNode(getMonth(thisMonth-1) + " ");
           tdMonth.appendChild(txtMonth);
	// Print the year heading: If year<0, negate and print "BCE"; if 0<year<1000, print "CE":
//           var br = document.createElement("br");
//           tdMonth.appendChild(br);
           if( thisYear < 0 ) yearString = -thisYear + " BCE";
           else if( thisYear < 1000 ) yearString = thisYear + " CE";
           else yearString = thisYear;
           var txtYear = document.createTextNode(yearString);
           tdMonth.appendChild(txtYear);
        //
           tr.appendChild(tdMonth);
        //
           var tdRight = document.createElement("td");
           tdRight.onclick = nextMonth;
           tdRight.dateObject = targetId;
           var monthForward = document.createTextNode(">");
           tdRight.appendChild(monthForward);
           tdRight.className = "calendarNavigate";
           tr.appendChild(tdRight);
           var tdRightRight = document.createElement("td");
           tdRightRight.onclick = nextYear;
           tdRightRight.dateObject = targetId;
           var yearForward = document.createTextNode(">>");
           tdRightRight.appendChild(yearForward);
           tdRightRight.className = "calendarNavigate";
           tr.appendChild(tdRightRight);
        //
           tb.appendChild(createDaysRow(daysInAWeek));
	
           // Get the day of week of the first of the month:
           var firstDay=dayOfWeek( toJulian( new CalendarDate(thisYear, thisMonth, 1) ) ); 
             //alert( Day[ firstDay ] );
	
           trDays = document.createElement("tr");
           // First week:
           for(i=0;i<firstDay;i++){
              tdDay  = document.createElement("td");
              txtDay = document.createTextNode(" ");
              tdDay.appendChild(txtDay);
              trDays.appendChild(tdDay);
	   }
           for(d=1;i<daysInAWeek;i++,d++){
              // Special handling for October of 1582:
              if( d==5 && thisMonth==10 && thisYear==1582 ) d+=10;
              tdDay  = document.createElement("td");
              tdDay.className = "calendar";
              if(d==thisDay) tdDay.className="thisday";
              tdDay.onclick = setDate;
              tdDay.dateObject = targetId;
              tdDay.day = d;
              txtDay = document.createTextNode(d);
              tdDay.appendChild(txtDay);
              trDays.appendChild(tdDay);
           }
           tb.appendChild(trDays);
	
           // Subsequent weeks;
           var lastDayOfMonth=daysInMonth[thisMonth-1];
           for(j=1;j<6 && d<=lastDayOfMonth;j++){
           trDays = document.createElement("tr");
            // Days in this month:
            for( i=0; i<daysInAWeek && d<=lastDayOfMonth;i++,d++){  
              tdDay  = document.createElement("td");
              tdDay.className = "calendar";
              if(d==thisDay) tdDay.className="thisday";
              tdDay.onclick = setDate;
              tdDay.dateObject = targetId;
              tdDay.day = d;
              txtDay = document.createTextNode(d);
              tdDay.appendChild(txtDay);
              trDays.appendChild(tdDay);
            }
            // Finish out the row:
            for(;i<daysInAWeek;i++){
              tdDay  = document.createElement("td");
              if(d==thisDay) tdDay.className="thisday";
              txtDay = document.createTextNode(" ");
              tdDay.appendChild(txtDay);
              trDays.appendChild(tdDay);
            }
            tb.appendChild(trDays);
	}
        return tab;
}



