/*
    PSESD
    upcomingevents.js
    
    Created by Marcus Lopes
    April 22nd 2011

    This script queries Google Calendar
    and returns the three most upcoming
    events
    
    REQUIRES jquery,
            js/sortdate.js,
            js/icalendar/jquery.icalendar.min.js
            
*/
//timeDiff: Function to measure script efficiency, for debug only
var timeDiff  =  {
    setStartTime:function (){
        d = new Date();
        time  = d.getTime();
    },

    getDiff:function (){
        d = new Date();
        return (d.getTime()-time);
    }
}

/* Function showTime: Receives date and displays user friendly time 00:00 AM/PM
    @param time Date object to extract time from.
*/
function showTime(time)
{
    var thisMinute = time.getMinutes();
    var thisHour = time.getHours();
    var ampm = (thisHour < 12)? "AM" : "PM";
    
    thisHour = (thisHour > 12)? thisHour - 12 : thisHour;
    thisHour = (thisHour == 0)? 12 : thisHour;
    thisMinute = (thisMinute < 10)?(0 + '' + thisMinute) : thisMinute;
    return thisHour + ":" + thisMinute + ampm;
}
/* function showDuration: Receives start_time, end_time and returns
    user friendly duration time 00:00 AM/PM - 00:00 AM/PM, Month Day
    @param startTime Date Object that represents the start time of an event
    @param endTime Date Object that represents the end time of an event
*/
function showDuration(start_time,end_time)
{
    //days of the week in the RFC 2445 format
    var MONTHS = new Array("January", "February", "March",
        "April", "May", "June", "July", " August",
        "September", "October", "Novemeber", "December");
    // Generate string with Month and days of the event
    var month_string = '';
    var start_month = start_time.getMonth();
    var end_month = end_time.getMonth();
    var start_day = start_time.getDate();
    var end_day = end_time.getDate();
    var start_year = start_time.getFullYear();
    var end_year = end_time.getFullYear();
    
    //format start and end times to the 00:00AM/PM format
    start_time_format = showTime(start_time);
    end_time_format = showTime(end_time);
    
    // if start_time is equal to end time at 12:00AM, it is an all day event
    if((start_time_format == "12:00AM") && (start_time_format == end_time_format))
    {
        /* All day events go until the next day at midnight
          so we need to remove one day from it in order to get
          the last day from the event
          Google does not have a RRULE for all day events,
          thus this workaround is needed.
        */
        var subtractTime = end_time.getTime() - 1000*60*60*24;
        end_time.setTime(subtractTime);
        end_month = end_time.getMonth();
        end_day = end_time.getDate();
        end_year = end_time.getFullYear();
        //update end_time_format into the date / time subtracted
        end_time_format = showTime(end_time);
        
        if(start_year != end_year) // if years are different, display years too
        {
            month_string = start_year + ", " + MONTHS[start_month] + " "  +
                start_day + " - " + end_year +
                ", " + MONTHS[end_month] + " " +
                end_day;
        }
        else if( start_month != end_month)// years are the same, display months and days only
        {
            month_string = MONTHS[start_month]  +
                " " + start_day + " " +
                " - " + MONTHS[end_month] +
                " " + end_day;
        }
        else if(start_day != end_day)// if days are different, the event lasts more than one day
        {
            month_string = MONTHS[start_month] + " " + start_day  +
                " - " + end_day; // assuming that start_day is less than end_day
        }
        else // event lasts only one day
        {
            month_string = MONTHS[start_month] + " " + start_day;
        }
    }
    else // this is not an all day event
    {
        if(start_year != end_year) // if years are different, display years too
        {
            /*
						month_string = start_year + ", " + MONTHS[start_month] + " "  +
                start_day + " " + + start_time_format + " - " + end_year +
                ", " + MONTHS[end_month] + " " +
                end_day + " " + end_time_format;
								
								*/
						month_string = start_year + ", " + MONTHS[start_month] + " "  +
                start_day + " - " + end_year +
                ", " + MONTHS[end_month] + " " +
                end_day + ", " + start_time_format + " - " + end_time_format;			
						
        }
        else if( start_month != end_month)// years are the same, display months and days only
        {
/*            month_string = start_time_format + " ," + MONTHS[start_month]  +
                " " + start_day + " " +
                " - " + MONTHS[end_month] +
                " " + end_day + " " + end_time_format;*/
						  month_string = MONTHS[start_month]  +
                " " + start_day + " - " +
                " - " + MONTHS[end_month] +
                " " + end_day + ",  " + start_time_format + " - " + end_time_format;
        }
        else if(start_day != end_day)// if days are different, the event lasts more than one day
        {
/*            month_string = start_time_format + ", " + MONTHS[start_month] + " " + start_day  +
                " - " + end_day + " " +
                end_time_format; // assuming that start_day is less than end_day
								*/
							month_string = MONTHS[start_month] + " " + start_day  + " - " + end_day + ", " + start_time_format + " - " +  end_time_format; // assuming that start_day is less than end_day
        }
        else // event lasts only one day
        {
          /*  month_string = start_time_format + ' - ' + end_time_format +  ", " +
                MONTHS[start_month] + " " + start_day;*/
					month_string = MONTHS[start_month] + " " + start_day + ', ' + start_time_format + ' - ' + end_time_format;
        }
    }
    return (month_string);
}

/* Workaround : Google .getValue() function does not return
  a functional RFC 2445. The workaround inserts begin and
  end blocks in order to make it functional.
  @param brokenString String containing RFC 2445 Vevent to be fixed
*/
function formatRecurrence(brokenString)
{
    brokenString = "BEGIN:VCALENDAR\n" + brokenString + "END:VCALENDAR";
    return brokenString;
}

/* Parses vevent string with JQuery plugin "JQuery ICalendar" into a JSON Object:
  http://keith-wood.name/icalendar.html
  @param recurrence RFC 2445 Object to be parsed
*/
function parseRecurrence(recurrence)
{
    //extract String value from Recurrence object
    recurrence = recurrence.getValue();
    try{ // assumes String is correct and try to parse
        var ical = $.icalendar.parse(recurrence); 
        ical = $.toJSON(ical, true);
        ical = eval('(' + ical + ')');
        return ical;
    }
    catch(wrongStruct) // if failed, try workaround to fix String
    {
        try
        {
            /* Workaround : Google .getValue() function does not return
              a functional RFC 2445. The workaround inserts begin and
              end blocks in order to make it functional.
            */
            var ical = formatRecurrence(recurrence);
            ical = $.icalendar.parse(ical);
            ical = $.toJSON(ical, true);
            ical = eval('(' + ical + ')');
            return ical;
        }
        catch(wrongStruct) // parsing failed
        {
            alert("Error:"+wrongStruct);
            return false;
        }
    }
}
/*
    function appendTimeLocationTag(String text):void
    Receives a String and appends its text to the events part of the website
    @param text String to be appended
*/
function appendTimeLocationTag(text)
{
     $("#upcoming p:last").append("<span class='Apple-style-span' \
        style='font-family:verdana, geneva; font-size: small;'>" + text + "</span><br />");
}
/*
    function appendContentTag(String content):void
    Receives a String and appends its text to the events description part of the website
    @param content String to be appended
*/
function appendContentTag(content)
{
   /* 
		var span_tag = "<span class='Apple-style-span'\
        style='font-family: verdana, geneva;\
        font-size: small;'>";
    $("#upcoming p:last").append(span_tag + content + '</span><br />');
		*/
}
/*
 function printEventTitle(EventEntry event):void
 Prints the title for an event
 @param event The Event Entry to print its title
*/
function printEventTitle(event)
{
    // Fetch the event title and description of the matches
    var title = event.getTitle().getText();
    
    //Displays Event name
    var p_tag = "<span class='eventtitle-home'>";
    $("#upcoming").append(p_tag + title + '</span>');
    //var a_tag = "<a href='#' style='font-weight:bold;'>";
    //$("#upcoming").append(a_tag + title + '</a><br />');
}
//print events that are non recurrent
function printNonRecurrent(event)
{
    //initialize arrays to receive the event times
    var times = new Array();
    var start_time = new Array();
    var end_time = new Array();


    // Fetch the event times
    times =  event.getTimes();
    // fetch event locations
    locations = event.getLocations();
    // Display event title
    printEventTitle(event);
    $("#upcoming").append("<p></p>");
    
    // Display event description
    var content = event.getContent().getText();
    ////appendContentTag(content);
    
    //timeDiff.setStartTime(); // 5737/0ms for sort inside loop, 46/0ms outside
    //get the closest event times
    start_time[0] = times[0].getStartTime();
    start_time[0] = start_time[0].getDate();// convert gdata.DateTime to Date
    end_time[0] = times[0].getEndTime();
    end_time[0] = end_time[0].getDate();// convert gdata.DateTime to Date
    //sort arrays
    start_time.sort(date_sort_asc);
    end_time.sort(date_sort_asc);
    
    //measure script efficiency
    //alert(timeDiff.getDiff());

    // Display start and end times for this event
    appendTimeLocationTag("When: " + showDuration(start_time[0],end_time[0]));
    
    // Display locations for this event
    var current_location = "";
    for(var z = 0; z < locations.length; z++)
    {
        current_location =locations[z].getValueString();
        // check if there is a location description before printing
       if(typeof(current_location) != 'undefined')
            if(current_location != "")
              appendTimeLocationTag("Location: " + locations[z].getValueString());
    }
}

/* function printEventDetails(EventEntry event)
    Receives an event entry and extracts the recurrence data from it
    @param event Entry Event to extract data from.
*/
function printEventDetails(event)
{
    // Fetch event recurrence
    var recurrence = event.getRecurrence();
    // Fetch and check for recurrence exceptions
    var recException = event.getEventStatus();
    
    //if event was not canceled, print it 
   if(recException.getValue() != google.gdata.EventStatus.VALUE_CANCELED)
        printNonRecurrent(event);// Print event in non recurrent mode(one per time)
}


function loadGoogleLibrary()
{
    // Load gdata library that includes ICalendar
    google.load("gdata", "2.x");
    google.setOnLoadCallback(getMyEntries);
}

function setupMyService() {
    var myService;
    myService = new google.gdata.calendar.CalendarService('Arts Impact');
    return myService;
}

function handleError(e) {
  alert("Could not connect to the calendar!");
  alert(e.cause ? e.cause.statusText : e.message);
}


function getMyEntries()
{
    //limit number of results
    var QUERY_MAX_RESULTS = 5;
    // initialize Calendar Service
    var myService = setupMyService();
    
    var feedUrl = "http://www.google.com/calendar/feeds/brjk858mlci665eo28hp8d9l20@group.calendar.google.com/public/full?futureevents=true&orderby=starttime&sortorder=ascending&max-results=5";
    // Create a CalendarEventQuery
    var query = new google.gdata.calendar.CalendarEventQuery(feedUrl);
    ////var current_date = new google.gdata.DateTime();
    // Set the query to order by start time
    ////current_date.setDate(new Date());
    ////query.setMinimumStartTime(current_date);
    ////query.setOrderBy("ORDERBY_START_TIME");
    ////query.setMaxResults(QUERY_MAX_RESULTS);

    
    
    // The callback method that will be called when getEventsFeed() returns feed data
    var callback = function(root)
    {
        // initialize variables to store the title and description
        var title;
        var content;

        // Obtain the array of matched CalendarEventEntry
        var eventEntries = root.feed.getEntries();
        
        // If there are matches for the query, print events
        if (eventEntries.length > 0) { // there are events, display header for Events Section
        var header = $("\
            <h3 style='margin-top:15px;'>\
                Arts Impact Events\
                <span style='font-size:.6em;float:right;'>\
                    <a href='about/events.php'\
                        style='font-weight:bold; vertical-align:middle;\
                        text-align:right;'>View Calendar\
                    </a>\
                </span>\
            </h3> ");
            $("#upcoming").before(header);
            for (var i = 0; i < eventEntries.length; i++) {
                var event = eventEntries[i];
                printEventDetails(event);
            }
        }
        //else {
        //    // No match is found for the query
        //    var header = $("\
        //        <h3 style='margin-top:15px;'>\
        //            Arts Impact Events\
        //        </h3>\
        //        <h3 style='margin-top:15px;'>\
        //            <span style='font-size:.6em;'>\
        //                <a href='about/events.php'\
        //                    style='font-weight:bold; vertical-align:middle;\
        //                    text-align:right;'>View Calendar\
        //                </a>\
        //            </span>\
        //        </h3>");
        //        $("#upcoming").before(header);
        //}
    };
    // Submit the request using the calendar service object.  Notice the 
    // CalendarEventQuery object is passed in place of the feed URI
    myService.getEventsFeed(query, callback, handleError);
}

//run script
loadGoogleLibrary();
