/*
  Copyright 2009 Nick Boughton <nb5@sanger.ac.uk>
        
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.
        
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  http://www.gnu.org/licenses/gpl.html
*/

var eventsList = new Array();

$(document).ready(function() {
  /*
   * Set up a reference for months and weekdays and bust out some AJAX to retrieve the events list
   */
  var month = new Array( 'January', 'February', 'March', 'April', 'May',
                         'June', 'July', 'August', 'September', 'October',
                         'November', 'December' );
 
  var daysInMonth = new Array( 31, 28, 31, 30, 31, 31, 31, 31, 30, 30, 30, 31 );
 
  var week = new Array( 'Sunday', 'Monday', 'Tuesday', 'Wednesday',
           'Thursday', 'Friday', 'Saturday' );
  
  var now            = new Date();
  var globalFullYear = now.getFullYear();
  var globalMonth    = now.getMonth();
  
  $.ajax({
      type:     "GET",
      url:      "/cgi-bin/events",
      dataType: "json",
      async:    false,
      success: function(data) { 
        $.each(data, function(i, item) { eventsList.push(item) });
      }
   });
  
  /*
   * Draw the calendar, bear in mind that inline CSS is the spawn of Satan
   * and any use of it will be punished with the violent impact of a high 
   * velocity spork into the offenders face.
   */ 

  function drawCalendar() {
    var today = new Date();
    // for our purposes we are always dealing with the first day of the month
    today.setDate(1);
    // if year and date aren't defined then we're dealing with the current month/year
    switch ($(this).attr('id')) {
      case 'monthBack':
        today.setMonth( (globalMonth - 1) );
        today.setYear( globalFullYear );
        globalMonth--;
	break;
      case 'monthForward':
        today.setMonth( (globalMonth + 1) );
        today.setYear( globalFullYear );
        globalMonth++;
	break;
      case 'yearBack':
        today.setYear( (globalFullYear - 1) );
        today.setMonth( globalMonth );
        globalFullYear--;
	break;
      case 'yearForward':
        today.setYear( (globalFullYear + 1) );
        today.setMonth( globalMonth );
        globalFullYear++;
	break;
      case 'calFooter':
        var newDate = new Date();
        today.setFullYear( newDate.getFullYear() );
        globalFullYear = newDate.getFullYear();
        today.setMonth( newDate.getMonth() );
        globalMonth = newDate.getMonth();
    }
    
    // izzywizzy let's get busy
    var calendarHtml = new String();
    
    // Ok we need to check for leap years and adjust accordingly
    if( today.getMonth() == 1 && today.getFullYear() % 1000 != 0 && today.getFullYear() % 4 == 0 ) {
      daysInMonth[1]++;
    }

    // Create the calendar table header, this is so much cleaner than the original!
    calendarHtml += '<table id="calendarTable" cellspacing="0">';
    calendarHtml += '  <tr>';
    calendarHtml += '    <td class="calHeader" id="yearBack">&nbsp;&lt;&lt;</td>';
    calendarHtml += '    <td class="calHeader" id="monthBack">&lt;</td>';
    calendarHtml += '    <td class="calHeader" colspan="3"><b>' + month[today.getMonth()].substr(0, 3) + '&nbsp;&nbsp;' + today.getFullYear() + '</b></td>';
    calendarHtml += '    <td class="calHeader" id="monthForward">&gt;</td>';
    calendarHtml += '    <td class="calHeader" id="yearForward">&gt;&gt;&nbsp;</td>';
    calendarHtml += '  </tr>';
    calendarHtml += '  <tr>';
    for( var i = 0; i < week.length; i++ ) { 
      calendarHtml += '    <td>' + week[i].substr(0, 3) + '</td>';
    }
    calendarHtml += '  </tr>';
   
    /* 
     * every cell must have a class="day" and an id for its day number that way we can then run
     * checkEvents next and hilight days with events. All days will have an onclick bind event
     * attached to them but the function needs to be able to process and print multiple events
     * for any given day. Also I'm well aware that the indentation is unnecessary but I like it.
     */
    var j;
    var firstDay = today.getDay();
    for( var i = 0; i < daysInMonth[today.getMonth()]; i++ ) {
      calendarHtml += '  <tr>'
      for( var j = 0; j < 7; j++ ) {
        if( i < firstDay || i >= daysInMonth[today.getMonth()] ) {
          calendarHtml += '    <td class="day" />';
	  firstDay--;
        } else {
	  i++;
          calendarHtml += '    <td class="day" id="' + i + '">' + i + '</td>';
        }
      }
      i--; 
      calendarHtml += '  </tr>';
    }
    calendarHtml += ' <tr><td colspan="7" id="calFooter">Return to Current Month</td></tr>';
    calendarHtml += '</table>';
    
    // Overwrite whatevers currently drawn with this little baby
    $('#calendar').html(calendarHtml);

    // Time to hilight and bind the days on which events occur
    checkEvents();    
    $('.calHeader').click(drawCalendar);
    $('#calFooter').click(drawCalendar);
  }
 
  /*
   * checkEvents is very limited in its scope, it merely has to add an extra class of 'hilight' and bind a click event to the cell
   */
  function checkEvents() {
    for( var i = 0; i < eventsList.length; i++ ) {
      // let's assign some of this arrays values to avoid confusion, use parseInt to
      // ensure these are interpreted as numbers rather than strings.
      var startYear = parseInt(eventsList[i][0]), startMonth = parseInt(eventsList[i][1] - 1), startDay = parseInt(eventsList[i][2]);
      var endYear   = parseInt(eventsList[i][3]), endMonth   = parseInt(eventsList[i][4] - 1), endDay   = parseInt(eventsList[i][5]);
      var limit;
      if( startMonth == globalMonth && startYear == globalFullYear ) {
        if( endMonth == startMonth ) { 
          limit = endDay; 
        } else if( endMonth != startMonth ) { 
          limit = daysInMonth[startMonth];
        }
        for( var j = startDay; j <= limit; j++ ) {
          var selector = '#' + j;
          if( !$(selector).hasClass('calHilighted') ) {
            $(selector).addClass('calHilighted');
            $(selector).click(printEvents);
          }
        }
      }
    }
  }

  function printEvents() {
    var generatedHtml = '<div id="outputContainer">';
    var day = $(this).attr('id');
    // I know, I replicated code from the previous function, really there should be an
    // iterateEvents function that can have a unique callback thrown in. I'll put that
    // on the todo list.
    for( var i = 0; i < eventsList.length; i++ ) {
      // let's assign some of this arrays values to avoid confusion
      var startYear    = parseInt(eventsList[i][0]), startMonth    = parseInt(eventsList[i][1] - 1), startDay    = parseInt(eventsList[i][2]);
      var endYear      = parseInt(eventsList[i][3]), endMonth      = parseInt(eventsList[i][4] - 1), endDay      = parseInt(eventsList[i][5]);
      var deadlineYear = parseInt(eventsList[i][6]), deadlineMonth = parseInt(eventsList[i][7] - 1), deadlineDay = parseInt(eventsList[i][8]);
      var eventType = eventsList[i][9], eventTitle = eventsList[i][10], url = eventsList[i][11], brandImgUrl = eventsList[i][12];
      var brandName = eventsList[i][13];
      var limit;
      if( endMonth == startMonth ) { 
        limit = endDay; 
      } else if ( endMonth != startMonth ) { 
        limit = daysInMonth[startMonth]; 
      }
      for( var j = startDay; j <= limit; j++ ) {
        if( j == day && startMonth == globalMonth ) {
          var dates = new Array();
          dates = formatSearchDates(startYear,startMonth,startDay,endYear,endMonth,endDay,deadlineYear,deadlineMonth,deadlineDay);
          generatedHtml += generateOutputHtml(dates[0], dates[1], eventTitle, eventType, url, brandImgUrl, brandName);
        }
      }
    }
    generatedHtml += '</div>';
    // id=content is the current default for the calendar system but obviously it can be changed
    $('#content').html(generatedHtml);
  }

  function formatSearchDates(startYear, startMonth, startDay, endYear, endMonth, endDay, deadlineYear, deadlineMonth, deadlineDay) {
    var dates = new Array();
    if(isNaN(deadlineDay) || isNaN(deadlineMonth) || isNaN(deadlineYear) || deadlineDay == 0 ) {
      dates[1] = 'T.B.A';
    } else {
      dates[1] = appendSuffix(deadlineDay) + " of " + month[deadlineMonth] + ", " + deadlineYear;
    }
    if( /0000/.test(endYear) || endDay == startDay ) {
      dates[0] = appendSuffix(startDay) + " of " + month[startMonth]  + ", " + startYear;
    } else {
      if( endMonth == startMonth ) {
        dates[0] = appendSuffix(startDay) + " - " + appendSuffix(endDay) + " of " + month[endMonth] + ", " + endYear;
      } else if( startMonth != endMonth ) {
        dates[0] = appendSuffix(startDay) + " of " + month[startMonth];
	if( startYear != endYear ) {
	  dates[0] += ", " + startYear + " - ";
	} 
	dates[0] += " - " + appendSuffix(endDay) + " of " + month[endMonth] + ", " + endYear;
      }
    }
    return dates;
  }

  // Not too sure how accurate this is, it may need some work.  
  function appendSuffix(day) {
   var ext;
   if ( /(\d|)1$/.test(day) && !/^11$/.test(day) ) {
     ext = 'st';
   } else if ( /^1\d+/.test(day) ) {
     ext = 'th';
   } else if ( /2$/.test(day) ) {
     ext = 'nd';
   } else if ( /3$/.test(day) ) {
     ext = 'rd';
   } else if ( /(4|5|6|7|8|9|0)$/.test(day) ) {
     ext = 'th';
   }
   return day + ext; 
  }

  function generateOutputHtml(dateRangeFormatted, appDeadlineFormatted, eventTitle, eventType, url, brandImgUrl, brandName) {
    var outputHtml = new String();
    if( eventType.length < 1 ) {
      eventType = brandName;
    }
    outputHtml += ' <table class="search_result_tbl">';
    outputHtml += '   <tr>';
    outputHtml += '     <td colspan="3"><a href="' + url + '" target="_new"><h6>' + eventTitle + '</h6></a></td>';
    outputHtml += '   </tr>';
    outputHtml += '   <tr>';
    outputHtml += '     <td class="col1"><img src="' + brandImgUrl + '" /></td>';
    outputHtml += '     <td class="col2">Type of event:</td>';
    outputHtml += '     <td class="col3">' + eventType + '</td>';
    outputHtml += '   </tr>';
    outputHtml += '   <tr>';
    outputHtml += '     <td class="col1"></td>';
    outputHtml += '     <td class="col2">Dates:</td>';
    outputHtml += '     <td class="col3">' + dateRangeFormatted + '</td>';
    outputHtml += '   </tr>';
    outputHtml += '   <tr>';
    outputHtml += '     <td class="col1"></td>';
    outputHtml += '     <td class="col2">Application deadline:</td>';
    outputHtml += '     <td class="col3">' + appDeadlineFormatted + '</td>';
    outputHtml += '   </tr>';
    outputHtml += ' </table>';
    outputHtml += ' <br />';
    return outputHtml;
  }
  
  // Finally call the initial draw
  drawCalendar();
});
