/**
 * A Calendar will always be a table with a header row for the month,
 *  a nav bar right below it for control,
 *  followed by a 7x6 grid,
 *  and finally a special controller only displayed if the user has the latest DOM. 
 *  A 7x6 grid is the maximum size of a calendar
 *  In the event the calendar requires:
 *   only 4 rows, the top and bottom will use the dates from other months
 *   only 5 rows, the bottom row will use the dates from the next month
 *
 */  
Calendar.MONTHS = new Array(
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
);
Calendar.WEEKDAYS = new Array(
  "Su",
  "M",
  "Tu",
  "W",
  "Th",
  "F",
  "Sa"
);
  

function Calendar( oDate, id )
{
  this.date = null;
  this.origDate = oDate;
  this.id = id;
  
  if (oDate==null)
    this.setDate(new Date());
  else
    this.setDate(oDate);
    
  //create a static manager Object that will keep record of the various Calendar instances
  if (Calendar.MANAGER==null)
  {
    Calendar.MANAGER = new Object();
  }
  Calendar.MANAGER[id] = this;
  
  
  // init the 7x6 table matrix
  this.table = new Array(42);
  this.updateTable();
  this.display();
}


Calendar.prototype.getLastMonth = function()
{
  var lastMonth = this.date.getMonth()-1;
  var lastMonthsYear = this.date.getFullYear();
  var currDay = this.date.getDate();
  var daysLastMonth = null;
  if (lastMonth<0)
  {
    lastMonth = Calendar.MONTHS.length-1;
    lastMonthsYear--;
  }
  daysLastMonth = Calendar.getDaysInMonth(lastMonthsYear, lastMonth);
  
  if (daysLastMonth < currDay)
  {
    currDay = daysLastMonth;
  }
  return new Date(lastMonthsYear, lastMonth, currDay);
};

Calendar.prototype.getNextMonth = function()
{
  var nextMonth = this.date.getMonth()+1;
  var nextMonthsYear = this.date.getFullYear();
  var currDay = this.date.getDate();
  var daysNextMonth = null;
  
  if (nextMonth==Calendar.MONTHS.length)
  {
    nextMonth = 0;
    nextMonthsYear++;
  }
  daysNextMonth = Calendar.getDaysInMonth(nextMonthsYear, nextMonth);
  
  if (daysNextMonth < currDay)
  {
    currDay = daysNextMonth;
  }
  return new Date(nextMonthsYear, nextMonth, currDay);
};

Calendar.getDaysInMonth = function( year, month )
{
  var DIM = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
  var dateobj = new Date(year, month, 01);
  if (month==1 && year%4==0 && year%100!=0)
    return DIM[month]+1;
  else if (month==1 && year%400==0)
    return DIM[month]+1;
  else
    return DIM[month];
};

Calendar.prototype.updateTable = function()
{
  var newTable = new Array(42);
  var lastMonth = this.getLastMonth();
  var nextMonth = this.getNextMonth();
  var monthDays = Calendar.getDaysInMonth(this.date.getFullYear(), this.date.getMonth());
  var lastMonthDays = Calendar.getDaysInMonth(lastMonth.getFullYear(), lastMonth.getMonth());
  var nextMonthDays = Calendar.getDaysInMonth(nextMonth.getFullYear(), nextMonth.getMonth());
  var dFirstDayOfMonth = new Date(this.date.getFullYear(), this.date.getMonth(), 1);
  var firstDayOfMonth = dFirstDayOfMonth.getDay();
  
  //determine which row the calendar should start on
  if (monthDays <= 29)
  {
    if (firstDayOfMonth > 1)
      startRow = 0;
    else
      startRow = 1;
  }
  else
  {
    if (firstDayOfMonth > 3)
      startRow = 0;
    else
      startRow = 1;
  }
  
  lastMonthsDaysToShow = (startRow*7)+firstDayOfMonth;
  nextMonthsDaysToShow = 42-(lastMonthsDaysToShow+monthDays);
  
  for(var days=lastMonthDays-lastMonthsDaysToShow+1,i=0; i<lastMonthsDaysToShow; days++, i++)
  {
    newTable[i] = new CalendarDay(new Date(lastMonth.getFullYear(), lastMonth.getMonth(), days),-1);
  }
  for(days=1; days<=monthDays; days++, i++)
  {
    thisMonthsDate = new Date(this.date.getFullYear(), this.date.getMonth(), days)
    newTable[i] = new CalendarDay(thisMonthsDate,0);
    if (days==Number(this.date.getDate())&&this.date.getFullYear()==this.origDate.getFullYear()&&this.date.getMonth()==this.origDate.getMonth())
    {  newTable[i].cellClass = 'dayselected'; }
  }
  for(days=1; days<=nextMonthsDaysToShow; days++, i++)
  {
    newTable[i] = new CalendarDay(new Date(nextMonth.getFullYear(), nextMonth.getMonth(), days),1);
  }
  this.table = newTable;
  this.updateManager();
};

Calendar.prototype.setDate = function( oDate )
{
  this.date = oDate;
};

Calendar.prototype.display = function()
{
  var today = new Date();
  var HTML = '' +
   '<table id="'+this.id+'">' +
   '<tr><td colspan="7" id="'+this.id+'_yearrow">' +
   '<span id="'+this.id+'_lastmonth">&lt;&lt;&nbsp;&nbsp;</span>' +
   '<span id="'+this.id+'_year">'+this.date.getFullYear()+"</span>" + 
   '<span id="'+this.id+'_nextmonth">&nbsp;&nbsp;&gt;&gt;</span>' +
   '</td></tr>' +
   '<tr><td colspan="7" id="'+this.id+'_monthrow">' +
   '<span id="'+this.id+'_month">'+Calendar.MONTHS[this.date.getMonth()]+"</span>" + 
   '</td></tr>';
   
  HTML += '<tr>';
  for(col=0;col<Calendar.WEEKDAYS.length;col++)
  {
   HTML += '<td ' +
    'id="'+this.id+'_'+Calendar.WEEKDAYS[col]+'" ' +
    'class="'+this.id+'_weekday">' +
    Calendar.WEEKDAYS[col] +
    '</td>';
  }
   HTML += '</tr>';
  for(row=0,i=0;row<6;row++)
  {
    HTML += '<tr>';
    for(col=0;col<7;col++,i++)
    { 
      HTML += '<td id="'+this.id+'_'+row+'_'+col+'" '+
              'class="'+this.id+'_'+this.table[i].cellClass+'">'+
              '<a href="/events/index?d='+this.table[i].date.getFullYear()+'-'+Number(Number(this.table[i].date.getMonth())+1)+'-'+this.table[i].date.getDate()+'" class="'+this.id+'_day">'+
              this.table[i].toHTML()+'</a></td>';
    }
    HTML += '</tr>';
  }
  HTML += '</table>';
  document.write(HTML);
  
  document.getElementById(this.id+"_nextmonth").onclick = this.gotoNextMonth();
  document.getElementById(this.id+"_lastmonth").onclick = this.gotoLastMonth();
};

Calendar.prototype.gotoNextMonth = function()
{
  return Calendar.update(this.id, "getNextMonth");
};
Calendar.prototype.gotoLastMonth = function()
{
  return Calendar.update(this.id, "getLastMonth");
};

Calendar.prototype.updateManager = function()
{
  Calendar.MANAGER[this.id] = this;
};

Calendar.update = function(id, dateFunc)
{
  return function()
  { 
    obj = Calendar.MANAGER[id];
    obj.date = obj[dateFunc]();
    obj.updateTable();
    obj.updateManager();
    //uses td id's to update the innerHTML and className from the table grid
    document.getElementById(id+"_month").innerHTML = Calendar.MONTHS[obj.date.getMonth()];
    document.getElementById(id+"_year").innerHTML = obj.date.getFullYear();
    
    for(row=0,i=0;row<6;row++)
    {
      for(col=0;col<7;col++,i++)
      {
        document.getElementById(id+"_"+row+"_"+col).innerHTML = 
          '<a href="/events/index?d='+obj.table[i].date.getFullYear()+'-'+Number(Number(obj.table[i].date.getMonth())+1)+'-'+obj.table[i].date.getDate()+'" class="'+obj.id+'_day">'+obj.table[i].toHTML()+'</a>';
        document.getElementById(id+"_"+row+"_"+col).className = id+"_"+obj.table[i].cellClass;
      }
    }
  };
};

Calendar.prototype.changeMonth = function( oDate ) 
{
  //this.getNextMonth
};

function CalendarDay(oDate, flagMonth)
{
  var today = new Date();
  this.date = oDate;
  this.dayNum = oDate.getDate();
  this.flagMonth = flagMonth;
  currDay = this.date;
  if (currDay.getMonth() == today.getMonth() && currDay.getDate() == today.getDate() && currDay.getFullYear() == today.getFullYear())
    this.cellClass = 'today';
  else if (flagMonth<0)
    this.cellClass = "lastmonth";
  else if (flagMonth>0)
    this.cellClass = "nextmonth";
  else
    this.cellClass = "thismonth";
}

CalendarDay.prototype.toHTML = function()
{
  return this.dayNum;
};
