var FEED_URI = 'https://www.google.com/calendar/feeds/bhl353l7h0ivela8m28cfij144@group.calendar.google.com/public/full';

String.prototype.contains = function(it) {
   return this.indexOf(it) != -1;
};

function createEvent(e, hide) {
   var eventTime = e.getTimes()[0];

   var start = eventTime.getStartTime();
   var end = eventTime.getEndTime();

   var reTrailingZeroes = /:00(am|pm)$/i;

   var time = sprintf('%s to %s',
      start.getDate().toString("h:mmtt").toLowerCase().replace(reTrailingZeroes, '$1'),
      end.getDate().toString("h:mmtt").toLowerCase().replace(reTrailingZeroes, '$1'));

   if (start.dateOnly || end.dateOnly) {
      time = "all day";
   }

   var classes = ['event'];

   if (hide) {
      classes.push('future');
   } else {
      classes.push('search-result');
   }

   var format = {
      title: e.getTitle().getText(),
      content: e.getContent().getText(),
      time: time,
      date: start.getDate().toString('M/d/yyyy'),
      classes: classes.join(' '),
      location: e.getLocations()[0].getValueString()
   };

   return $(sprintf('<div class="%(classes)s">' +
      '<h3>%(title)s</h3>' +
      '<input type="hidden" class="date" value="%(date)s" />' +
      '<input type="hidden" class="title" value="%(title)s" />' +
      '<input type="hidden" class="location" value="%(location)s" />' +
      '<h4 class="time">%(time)s</h4>' +
      '<div class="content">%(content)s</div>' +
      '</div>', format));
}

function createFeaturedEvent(e, image) {
   var eventTime = e.getTimes()[0];

   var start = eventTime.getStartTime();
   var end = eventTime.getEndTime();

   var title = e.getTitle().getText();

   var href = sprintf('/calendar/#search-by=featured-event&query=%s&title=%s', start.getDate().toString('M/d/yyyy'), title);

   var format = {
      date: start.getDate().toString('dddd, MMMM d'),
      title: title,
      href: href
   };

   var image_string = '';

   if (image) {
      if (e.properties.ImageThumbnail &&
         e.properties.ImageThumbail != '') {
         image_string = sprintf('<a href="%s"><img src="%s" /></a>', href, e.properties.ImageThumbnail);
      }
   }

   return $(sprintf('<div class="event">' +
      '<div class="event-title accent-text">' +
      image_string +
      '<a href="%(href)s">%(title)s</a>' +
      '</div>' +
      '%(date)s' +
      '</div>', format));
}

function createService() {
   return new google.gdata.calendar.CalendarService('bam-calendar');
}

function createQuery() {
   var query = new google.gdata.calendar.CalendarEventQuery(FEED_URI);

   // Create and set the minimum and maximum start time for the date query
   var startMin = new google.gdata.DateTime(Date.today(), true);
   var startMax = new google.gdata.DateTime(Date.today().add(12).months(), true);

   query.setSingleEvents(true);

   query.setMinimumStartTime(startMin);
   query.setMaximumStartTime(startMax);

   query.setOrderBy('starttime');
   query.setSortOrder('ascending');
   query.setMaxResults('100');

   return query;
}

function getFeaturedEvents(events, property) {
   var featured = $.grep(events, function(n, i) {
      if (n.properties[property] &&
         n.properties[property].toLowerCase() == 'true') {
         return true;
      }

      return false;
   });

   var pruned_featured = [];

   for (var i = 0; i < featured.length && pruned_featured.length < 2; i++) {
      pruned_featured.push(featured[i]);
   }

   for (var i = pruned_featured.length; i < events.length && pruned_featured.length < 2; i++) {
      if (!events[i].properties[property] || events[i].properties[property].toLowerCase() != 'true') {
         pruned_featured.push(events[i]);
      }
   }

   return pruned_featured;
}

function fillProperties(events) {
   for (var i = 0; i < events.length; i++) {
      var properties = events[i].getExtendedProperties();
      var properties_object = {};

      for (var j = 0; j < properties.length; j++) {
         properties_object[properties[j].name] = properties[j].value;
      }

      events[i].properties = properties_object;
   }
}

// The callback method that will be called when getEventsFeed() returns feed data
var mainCallback = function(root) {
   // Obtain an array of objects of type CalendarEventEntry
   var entries = root.feed.getEntries();

   var currentDay = false;

   for (var i = 0; i < entries.length; i++ ) {
      var e = entries[i];

      var eventTime = e.getTimes()[0];

      var start = eventTime.getStartTime().getDate();
      var end = eventTime.getEndTime().getDate();

      if (Date.today().compareTo(start.clone().clearTime()) == 0) {
         $("#today").append(createEvent(e, false));
      } else {
         var hide = false;

         if (start.clone().clearTime().compareTo(Date.today().add(2).weeks()) > 0) {
            // Mark events occurring further than two weeks out
            hide = true;
         }

//         if (!currentDay || currentDay.compareTo(start.clone().clearTime()) != 0) {
            var classes = ['dateHeader'];

            if (hide) {
               classes.push('future');
            }

            $("#cal-list").append(sprintf('<h3 class="%s">%s</h3>', classes.join(' '),
               start.toString('MMMM d, yyyy')));

//            currentDay = start.clone().clearTime();
//         }

         $("#cal-list").append(createEvent(e, hide));
      }
   }

   setupMiniCalendar(entries);

   $(document).trigger('eventsLoaded', { events: entries });
}

// The callback method that will be called when getEventsFeed() returns feed data
var miniCallback = function(root) {
   var entries = root.feed.getEntries();

   setupMiniCalendar(entries);

   $(document).trigger('eventsLoaded', { events: entries });
}

// Error handler to be invoked when getEventsFeed() produces an error
var handleError = function(error) {
   //console.log("Google API error", error);
}

function hasDate(events, date) {
   for (var i = 0; i < events.length; i++) {
      if (events[i].date.compareTo(date) == 0) {
         return i;
      }
   }

   return false;
}

function setupMiniCalendar(entries) {
   var events = [];

   for (var i = 0; i < entries.length; i++ ) {
      var e = entries[i];

      var eventTime = e.getTimes()[0];

      var start = eventTime.getStartTime().getDate();
      var end = eventTime.getEndTime().getDate();

      var has = hasDate(events, start.clone().clearTime());

      if (has === false) {
         events.push({ date: start.clone().clearTime(), title: e.getTitle().getText() });
      } else {
         events[has].title += "\n" + e.getTitle().getText();
      }
   }

   $("#calendar").datepicker({
      dayNamesMin: ['S', 'M', 'TU', 'W', 'TH', 'F', 'S'],
      nextText: '&#x25B6;',
      prevText: '&#x25C0;',
      beforeShowDay: function(date) {
         for (var d in events) {
            if (date.clearTime().compareTo(events[d].date.clearTime()) == 0) {
               return Array(true, 'event', events[d].title);
            }
         }

         return Array(false, '');
      },
      onSelect: function(dateText, inst) {
         if ($("#cal-list").length) {
            // We're on the calendar page
            var dateString = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay).toString('M/d/yyyy');

            $.bbq.pushState({
               'search-by': 'day',
               'query': dateString
            });
         } else {
            // We're on a page with a mini calendar on it somewhere
            location.href = '/calendar/#search-by=day&query=' + Date.parse(dateText).toString('M/d/yyyy');
         }
      },
      onChangeMonthYear: function() {
         // XXX Prevent a lame tooltip from occurring
         window.setTimeout(function() {
            $(".ui-datepicker-header a").attr('title', null);
         }, 500);
      }
   });

   $(".ui-datepicker-title").live('click', function() {
      if ($("#cal-list").length) {
         // We're on the calendar page
         $.bbq.pushState({
            'search-by': 'month',
            'query': $(this).text().replace("\xa0", ' ')
         });
      } else {
         // We're on a page with a mini calendar on it somewhere
         location.href = '/calendar/#search-by=month&query=' + $(this).text().replace(' ', '+').replace("\xa0", '+');
      }
   });

   // XXX Prevent a lame tooltip from occurring
   $(".ui-datepicker-header a").attr('title', null);
}

function keywordChanged() {
   var query = $('#keyword').val();

   if (query == '' || query == 'calendar') {
      $.bbq.removeState();
   } else {
      $.bbq.pushState({
         'search-by': 'keyword',
         'query': query
      });
   }
}

function keywordSearch(query) {
   $('#search-term').html(sprintf('"%s"', query));
   $('#search-term').show();

   $('#keyword').val(query);

   $('#calendar-right div.event').each(function (index) {
      var $e = $(this);

      var title = $e.find('h3').eq(0).text();
      var program_location = $e.find('input.location').eq(0).val();
      var content = $e.find('.content').eq(0).text();

      var container = $e.prev('h3').text();

      var title_check = title.toLowerCase().contains(query.toLowerCase());
      var program_location_check = program_location.toLowerCase().contains(query.toLowerCase());
      var content_check = content.toLowerCase().contains(query.toLowerCase());

      var container_check = container.toLowerCase().contains(query.toLowerCase());

      if (title_check || program_location_check || content_check || container_check) {
         $e.addClass('search-result');
         $e.show();
      }
   });

   $('#calendar-right div.event, #cal-list > h3').highlight(query);
}

function programSearch(query) {
   $('#search-term').html(sprintf('Showing %s program events', query));
   $('#search-term').show();

   $('#calendar-right div.event input.location[value*="' + query + '"]')
      .closest('div.event').show().addClass('search-result');
}

function dateSearch(type, query) {
   var date = Date.parse(query);

   if (type == 'month') {
      $('#search-term').html(sprintf('Showing events in %s', query));
      $('#search-term').show();

      $('#calendar-right div.event input[value^="' + (date.getMonth() + 1) + '/"]')
         .filter('input[value$="/' + date.getFullYear() + '"]')
         .closest('div.event').show().addClass('search-result');
   } else if (type == 'day') {
      $('#search-term').html(sprintf('Showing events on %s', query));
      $('#search-term').show();

      $('#calendar-right div.event input[value="' + date.toString('M/d/yyyy') + '"]')
         .closest('div.event').show().addClass('search-result');
   }
}

function featuredSearch(query, title) {
   var date = Date.parse(query);

   $('#calendar-right div.event input[value="' + date.toString('M/d/yyyy') + '"]')
      .siblings('input[value="' + title + '"]')
      .closest('div.event').show().addClass('search-result');
}

function search(state) {
   if (state['query']) {
      $('#calendar-right div.event').hide();

      $('#search-by-' + state['search-by']).show();

      switch (state['search-by']) {
         case 'keyword':
            keywordSearch(state['query']);
            break;
         case 'program':
            programSearch(state['query']);
            break;
         case 'day':
         case 'month':
            dateSearch(state['search-by'], state['query']);
            break;
         case 'featured-event':
            featuredSearch(state['query'], state['title']);
            break;
         default:
            $.bbq.removeState();
      }

      $("#cal-list > h3").hide();

      // XXX For some reason .prev('h3') does't work here.
      $("#cal-list .event.search-result").prevAll('h3').eq(0).show();
      // Not sure why this was commented but it was causing /calendar/#search-by=month&query=April+2011 to only have 1 date displayed for the very last one
      $("#cal-list .event:visible").prev('h3').show();
   } else {
      $.bbq.removeState();
   }
}

