// File: calendar.js
// Desc: Displays a calendar month on an HTML page.


var calendar = new Calendar()

Calendar.monthNames = new Array( 
   'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
   'September', 'October', 'November', 'December' )
   
Calendar.days = new Array ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )
Calendar.leapdays = new Array ( 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )


// Class calendar -------------------------------------------------------------
function Calendar()
{
   // Member variables -------------------------------
   
   this.datesEvents = new Array()
   this.debug = false
   this.debugText = ''
   
   
   // Methods ----------------------------------------
   
   this.addEvent     = Calendar_addEvent
   this.daysInMonth  = Calendar_daysInMonth
   this.eventsForDay = Calendar_eventsForDay
   this.getMonthName = Calendar_getMonthName
   this.setDebugMode = Calendar_setDebugMode
   this.write        = Calendar_write
   this.writeWeek    = Calendar_writeWeek
   
}  // class Calendar


// Add an event to the calendar -----------------------------------------------
/*
   Parameters:
      year     -  The full year of the event (i.e., 2002)
      month    -  The month (1-12) of the event
      day      -  The day of the event (1-31)
      text     -  The text to display on the calendar
      tooltop  -  The text to display when the mouse hovers over the event
      url      -  The URL associated with the event if one exists
*/
function Calendar_addEvent( year, month, day, text, tooltip, url )
{
   var date = new Date( year, month-1, day )
   var dateEvents = this.datesEvents[date.getTime()]
   
   if( dateEvents == null )
      dateEvents = new CalendarDateEvents( date );
      
   dateEvents.addEvent( text, tooltip, url )
   this.datesEvents[date.getTime()] = dateEvents

}  // Calendar_addEvent


// Return the number of days in the month -------------------------------------
function Calendar_daysInMonth( year, month )
{
   var days = 1
   var leap = ( ( year % 4 ) == 0 ? true : false )
   
   if( leap && ( year % 100 ) == 0 )
      leap = false
      
   if( !leap && (year % 400 ) == 0 )
      leap = true

   if( leap )
      days = Calendar.leapdays[month-1];
   else
      days = Calendar.days[month-1];      

   return days

}  // Calendar_daysInMonth


// Write the events for the given day into the table --------------------------
function Calendar_eventsForDay( year, month, day )
{
   var htm = "", eventNo, event
   var date = new Date( year, month-1, day )
   var dateEvents = this.datesEvents[date.getTime()]
   var lf = this.debugText, numEvents
   var tooltip, url

   if( dateEvents != null )
   {
      htm += "<ul>" + lf
      
      for( eventNo = 0, numEvents = dateEvents.events.length; eventNo < numEvents; eventNo++ )
      {
         event = dateEvents.events[eventNo]
         
         if( event.tooltip != null )
            tooltip = "title='" + event.tooltip + "' ";
         else
            tooltip = "";
            
         if( event.url != null )
            url = "href='" + event.url + "' ";
         else
            url = "";
         
         htm += "<li>"
         
         if( url.length > 0 || tooltip.length > 0 )
            htm += "<a " + url + tooltip + ">" + event.text + "</a>" + lf;
         else
            htm += event.text + lf;
         
         if( eventNo < numEvents - 1 )
            htm += "<hr>";
                
         htm += "</li>" + lf
      }
      
      htm += "</ul>" + lf
   }
   
   return htm

}  // Calendar_eventsForDay


// Return the month and year as a string --------------------------------------
function Calendar_getMonthName( year, month )
{
   var m = Calendar.monthNames[month-1]
   str = m + ' ' + year

   return str

}  // Calendar_getMonthName


// Turn on the calendar debugging mode ----------------------------------------
function Calendar_setDebugMode()
{
   this.debug = true
   this.debugText = '<xx>'

}  // Calendar_setDebugMode


// Write the calendar month to the HTML page ----------------------------------
function Calendar_write( year, month )
{
   var htm = ""
   var lf = this.debugText
   
   // Create the surrounding <div>. Styles are in nhcc.css
   htm += "<a name='" + year + "_" + month + "'></a><p>" + lf
   htm += "<div class='calendar'>" + lf
   
   // Create the calendar table...
   htm += "<table>" + lf +
          "<colgroup>" + lf +
          "<col width='14.3%' span='7'>" + lf +
          "</colgroup>" + lf

   // Month being displayed...          
   htm += "<tr>" + 
          "<td class='month' colspan='7'>" + this.getMonthName( year, month ) + "</td>" + 
          "</tr>" + lf
   
   // Week day names...
   htm += "<tr>" + lf +
          "<th>Sunday</th>" + lf +
          "<th>Monday</th>" + lf +
          "<th>Tuesday</th>" + lf +
          "<th>Wednesday</th>" + lf +
          "<th>Thursday</th>" + lf +
          "<th>Friday</th>" + lf +
          "<th>Saturday</th>" + lf +
          "</tr>" + lf
          
   // Print the first week...
   var dow1 = ( new Date( year, month-1, 1 ) ).getDay()
   var days = this.daysInMonth( year, month )
   var lastdow = 7 - dow1
   var weekstr
   
   while( ( weekstr = this.writeWeek( lastdow, days, year, month ) ) != null )
   {
      htm += weekstr
      lastdow += 7
   }
   

   // Terminate the table and the div
   
   htm += "</table>" + lf
   htm += "</div>" + lf
   
   // The String code is in header.js...
   if( this.debug )
      htm = htm.fixupDebug()
      
   document.writeln( htm )

}  // Calendar_write


// Write the calendar week ----------------------------------------------------

function Calendar_writeWeek( lastdow, days, year, month )
{
   var lf = this.debugText
   var htm = ""
   var firstdow = lastdow - 7
   var more = ( lastdow - 6 > days ? false : true )
   var day

   if( !more )
      return null
   
   htm += "<tr>" + lf

   if( firstdow < 0 )
   {
      // Write the first week...
      htm += "<td  class='blank' colspan='" + -firstdow + "'>&nbsp;</td>" + lf
      
      for( day = 1; day <= lastdow; day++ )
      {
         htm += "<td><div class='day'>" + day + "</div>" + lf
         htm += this.eventsForDay( year, month, day )
         htm += "</td>" + lf
      }
   }
   else if( lastdow > days )
   {
      // Write the last week...
      for( day = lastdow - 6; day <= days; day++ )
      {
         htm += "<td><div class='day'>" + day + "</div>"
         htm += this.eventsForDay( year, month, day )
         htm += "</td>" + lf
      }
      
      htm += "<td class='blank' colspan='" + ( lastdow - days ) + "'>&nbsp;</td>" + lf
   }
   else
   {
      // Write the middle weeks...
      for( day = lastdow - 6; day <= lastdow; day++ )
      {
         htm += "<td><div class='day'>" + day + "</div>"
         htm += this.eventsForDay( year, month, day )
         htm += "</td>" + lf
      }
   }
   
   htm += "</tr>" + lf

   return htm

}  // Calendar_writeWeek


// Class CalendarDateEvents ---------------------------------------------------
function CalendarDateEvents( date )
{
   // Member variables -------------------------------
   this.date = date
   this.events = new Array()
   
   
   // Methods ----------------------------------------
   
   this.addEvent  = CalendarDateEvents_addEvent

}  // CalendarDateEvents


// Add an event to the calendar day -------------------------------------------
function CalendarDateEvents_addEvent( text, tooltip, url )
{
   var event = new CalendarDateEvent( text, tooltip, url )
   this.events[this.events.length] = event

}  // CalendarDateEvents_addEvent


// Class CalendarDateEvent --------------------------------------------------------
function CalendarDateEvent( text, tooltip, url )
{
   this.text = text
   this.tooltip = ( tooltip == null ? "No information available" : tooltip )
   this.url = url
   
}  // class CalendarDateEvent
