﻿/*
 * Will retrieve event information from the TYP356NE calendar
 * and update a nextEvent span node.
 *
 * The Google calendar event should be created as follows:
 *
 * Title 
 *
 *   The title should be short but descriptive enough to differentiate
 *   it from other titles of similar events. For example, "Tech Session
 *   at Boston Rim Works" or "Summer Barbeque at the Smiths'".
 *
 *   The title is all that appears in the web site's "next event" section
 *   on the home page which is why is needs to be "enough". But ideally
 *   it should also be very short so that it fits on one line.
 *
 *   Also it is only the title (and start time) which appears in the
 *   initial Calendar view. Other details are only accessible when the
 *   calendar entry is expanded.
 *
 * Date/Time
 *
 *   The date AND TIME of the event, both start AND finish (when known).
 *   For some events (such as multi-day events) it may make sense to omit
 *   the times. The default time zone is Eastern so you shouldn't need to
 *   change this.
 *
 * Where
 *
 *   The address of where the event is taking place. Google Calendar
 *   uses this for the MAP link so be as specific as you can. Typically
 *   supply either the street or business address.
 *
 * Calendar
 *
 *   Should always be TYP356NE.
 *
 * Description
 *
 *   Any additional information about this event. This section is 
 *   optional but where appropriate should be used to provide any
 *   additional information about the event such as any attendee limit,
 *   rain date and contact information. 
 *
 * Reminders
 * Show me as
 * Privacy
 * Add guests
 * Guests can
 *
 *   All of these sections should be left with their default values.
 */

google.load("gdata", "1");
google.setOnLoadCallback(init);

function init() {
  // init the Google data JS client library with an error handler
  google.gdata.client.init(handleGDError);
  loadCalendarByAddress('6um2lbfqu4imgu1spvic02k534@group.calendar.google.com');
}

/**
 * Callback function for the Google data JS client library to call when an error
 * occurs during the retrieval of the feed.  Details available depend partly
 * on the web browser, but this shows a few basic examples. In the case of
 * a privileged environment using ClientLogin authentication, there may also
 * be an e.type attribute in some cases.
 *
 * @param {Error} e is an instance of an Error 
 */
function handleGDError(e) {
  var eventSpan = document.getElementById('nextEvent');
  eventSpan.innerHTML = "Google calendar error: ";
  if (e instanceof Error) {
    /* alert with the error line number, file and message */
    eventSpan.innerHTML += 'Error at line ' + e.lineNumber +
          ' in ' + e.fileName + ' Message: ' + e.message;
    /* if available, output HTTP error code and status text */
    if (e.cause) {
      var status = e.cause.status;
      var statusText = e.cause.statusText;
      eventSpan.innerHTML += ' Root cause: HTTP error ' + status + ' with status text of: ' + statusText;
    }
  } else {
    eventSpan.innerHTML += e.toString();
  }
}

/**
 * Adds a leading zero to a single-digit number.  Used for displaying dates.
 */
function padNumber(num) {
  if (num <= 9) {
    return "0" + num;
  }
  return num;
}

function loadCalendarByAddress(calendarAddress) {
  var calendarUrl = 'http://www.google.com/calendar/feeds/' +
                    calendarAddress + 
                    '/public/full';
  // Initiate first action.
  fetchNextEvent(calendarUrl);
}

/**
 * Get the first event and then get all the events which start
 * during that first event's time. This is the set of events we
 * need to show.
 */  
 
function fetchNextEvent(calendarUrl) {
  var service = new google.gdata.calendar.CalendarService('gdata-js-client-samples-simple');
  var query = new google.gdata.calendar.CalendarEventQuery(calendarUrl);
  query.setOrderBy('starttime');
  query.setSortOrder('ascending');
  query.setFutureEvents(true);
  query.setSingleEvents(true);
  query.setMaxResults(1);
  service.getEventsFeed(query, gotNextEvent, handleGDError);
}

function gotNextEvent(feedRoot) {
  var entries = feedRoot.feed.getEntries();

  // Shouild be only one entry.
  if (entries.length < 1) {
    document.getElementById('nextEvent').innerHTML = "Events: Error 1";
    return;
  }
  
  // Now get all the events which span the time of the first event.
  var firstEntryTime = entries[0].getTimes()[0];
  fetchNextEvents(feedRoot.feed.id.$t, firstEntryTime.getStartTime(), firstEntryTime.getEndTime());
}

function fetchNextEvents(calendarUrl, startDate, endDate) {
  var service = new google.gdata.calendar.CalendarService('gdata-js-client-samples-simple');
  var query = new google.gdata.calendar.CalendarEventQuery(calendarUrl);
  query.setOrderBy('starttime');
  query.setSortOrder('ascending');
  query.setFutureEvents(false);
  query.setSingleEvents(true);
  query.setMinimumStartTime(startDate);
  query.setMaximumStartTime(endDate);
  query.setMaxResults(10);
  service.getEventsFeed(query, gotNextEvents, handleGDError);
}

function eventToText(event) {
    var days = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
    var months = ["January","February","March","April","May","June","July","August", "September","October","November","December"];
    var timeSuffix = "AM";
    var title = event.getTitle().getText();
    var startDateTime = null;
    var startJSDate = null;
    var times = event.getTimes();
    if (times.length > 0) {
      startDateTime = times[0].getStartTime();
      startJSDate = startDateTime.getDate();
    }
    var googleLinkHref= null;
    if (event.getHtmlLink() != null) {
      googleLinkHref= event.getHtmlLink().getHref();
    }
    var dateString = days[startJSDate.getDay()] + ", " + months[startJSDate.getMonth()] + " " + startJSDate.getDate() ;
    if (!startDateTime.isDateOnly()) {
      var hours = startJSDate.getHours();
      if (hours > 11) {
	    timeSuffix = "PM";
	  }
	  if (hours > 12) {
		hours = hours - 12;
      }
      dateString += ", " + hours + ":" + 
          padNumber(startJSDate.getMinutes()) +
          timeSuffix;
    }
    var where = null;
    if ("gd$where" in event && event.gd$where && event.gd$where.length>0) {
    	where = event.gd$where[0].valueString;
    }
    var content = event.getContent().getText();
    
    var ret = dateString + ": " + title;
    //if (where) {
    //	ret += " at " + where;
    //}

    //if (googleLinkHref!= null) {
    //  return dateString + ": <a href=\"" + googleLinkHref + "\">" + title + "<\a>"; 
    //} else {
    //  return dateString + ": " + title; 
    //}
    return ret;
}

function gotNextEvents(feedRoot) {
  var entries = feedRoot.feed.getEntries();
  var entryCount = entries.length;
  var eventSpan = document.getElementById('nextEvent');
  
  if (entryCount < 1) {
    eventSpan.innerHTML = "Unable to find any events from the calendar";
    return;
  }
  else if (entryCount == 1) {
    eventSpan.innerHTML = "Next event: " + eventToText(entries[0]);
    return;
  }
  else {
    var str = "Upcoming events:";
    for (var i=0; i<entryCount; i++) {
      str += "<br>" + eventToText(entries[i]);
    }
    eventSpan.innerHTML = str;
    return;
  }
}

