// Copyright 2009 Google Inc.  All Rights Reserved.

/**
 * @fileoverview Showcase pulls data from kraken gallery and from the
 * spreadsheet. It then combines and displays this data in the form
 * of a KML gallery.
 *
 * @author Michal Drewniak
 */

/**
 * Homepage promo class.
 * Connects Showcase class instance with DOM elements it will be manipulating.
 * @constructor
 */
earth.outreach.Showcase = function() {
  this.content = document.getElementById('showcase');
  this.message = document.getElementById('showcase-message');
  this.media = document.getElementById('landing-media');
  this.loadingImg = document.getElementById('showcase-loading');
  this.details = document.getElementById('showcase-details');
  this.earthapi = document.getElementById('earthapimap');

  this.searched = false;
  this.breaksearch = false;
  this.count = 0;
  this.start = 0;
  this.NUM_DISP = 6;
  this.NUM_ENTRIES = 100;
  this.SNIP_LEN = 80;
  this.entries = [];

  // Grab the URL params and load specified KML if present.
  this.params = earth.parseURLVar();
  if (this.params['kml']) {
    this.search(this.params['kml']);
  }

  this.loadingImg.className = '';
  this.getGalleryEntries(this.start);
  initShowcase_();

  /**
   * Attaches events to elements on the showcase page.
   * @private
   */
  function initShowcase_() {
    var quickLinks =
        document.getElementById('showcase-quick').getElementsByTagName('a');
    var searchForm = document.getElementById('showcase-search');
    var apiSizeLink = document.getElementById('showcase-size');

    // Quicklinks
    for (var i = 0, s = quickLinks.length; i < s; i++) {
      quickLinks[i].onclick = function(e) {
        earth.stopDefault(e);
        earth.outreach.showcase.quickLink(this.name);
      };
    }

    // API Size change link
    apiSizeLink.onclick = function(e) {
      earth.stopDefault(e);
      earth.outreach.showcase.changeApiSize(this);
    };

    // Search
    searchForm.onsubmit = function(e) {
      earth.stopDefault(e);
      earth.outreach.showcase.processSearch();
    }
  }
};


/**
 * Changes the size of the earth api window.
 * @param {Element} link Anchor element responsible for the resize
 *    of the api window.
 */
earth.outreach.Showcase.prototype.changeApiSize = function(link) {
  if (link.name == 'enlarge') {
    link.name = 'shrink';
    this.earthapi.style.width = '100%';
    this.earthapi.style.height = '400px';
    this.earthapi.style.clear = 'left';
    this.details.style.width = '100%';
    link.innerHTML = 'Shrink Google Earth window';
  } else {
    link.name = 'enlarge';
    this.earthapi.style.width = '50%';
    this.earthapi.style.height = '400px';
    this.earthapi.style.clear = '';
    this.details.style.width = '40%';
    link.innerHTML = 'Enlarge Google Earth window';
  }
};


/**
 * Creates navigation inside details display.
 * @param {string} currId Unique identified of the currently selected entry.
 * @private
*/
earth.outreach.Showcase.prototype.createDetailsNavigation_ = function(currId) {
  var back = document.getElementById('showcase-back');
  var next = document.getElementById('showcase-next');
  var prev = document.getElementById('showcase-prev');

  currId = parseInt(currId);
  this.toggleNav_('back', '');

  if (this.entries[currId + 1]) {
    this.toggleNav_('next', '');
  } else {
    this.toggleNav_('next', 'hidden');
  }

  if (this.entries[currId - 1]) {
    this.toggleNav_('prev', '');
  } else {
    this.toggleNav_('prev', 'hidden');
  }

  back.onclick = function(e) {
    earth.stopDefault(e);
    location.hash = '#';
    earth.outreach.showcase.showEntries();
  }

  next.onclick = function(e) {
    earth.stopDefault(e);
    earth.outreach.showcase.showDetails(e, currId + 1);
  }

  prev.onclick = function(e) {
    earth.stopDefault(e);
    earth.outreach.showcase.showDetails(e, currId - 1);
  }
};


/**
 * Creates unique entry ID using entrie's kmz url.
 * @param {string} url Kmz url.
 * @return {string} Unique entry id.
 * @private
 */
earth.outreach.Showcase.prototype.createEntryId_ = function(url) {
  if (url) {
    return escape(url.replace(/(\s)/g, '_'));
  } else {
    return '';
  }
};


/**
 * Attaches events to the navigation links based on the
 * currently displayed entries.
 * @private
 */
earth.outreach.Showcase.prototype.createNavigation_ = function() {
  var nextIndex = this.start + this.NUM_DISP;
  var prevIndex = this.start - this.NUM_DISP;
  var next = document.getElementById('showcase-next');
  var prev = document.getElementById('showcase-prev');

  next.onclick = function(e) {
    earth.outreach.showcase.start = nextIndex;
    earth.stopDefault(e);
    earth.outreach.showcase.showEntries();
  }

  prev.onclick = function(e) {
    earth.outreach.showcase.start = prevIndex;
    earth.stopDefault(e);
    earth.outreach.showcase.showEntries();
  }
};


/**
 * Creates a snippet from the passed text of the length size.
 * @param {string} fullText Text to create snippet from.
 * @param {number} size Maximum size of the snippet.
 * @return {string} Snippet (abbreviated version of fullText).
 * @private
 */
earth.outreach.Showcase.prototype.createSnippet_ = function(fullText, size) {
  var snippet = fullText.substr(0, size);
  var endIndex = snippet.lastIndexOf(' ');
  snippet = snippet.substring(0, endIndex);
  snippet += '... ';
  return snippet;
};


/**
 * Creates a snippet which ends at the last complete sentence.
 * @param {string} fullText Text to create snippet from.
 * @return {string} Snippet (abbreviated version of fullText).
 * @private
 */
earth.outreach.Showcase.prototype.createSnippetSentence_ = function(fullText) {
  var snippet = fullText.replace('...', '');
  var endIndex = snippet.lastIndexOf('.');
  snippet = snippet.substring(0, endIndex + 1);
  return snippet;
};


/**
 * Identifies entry id based on the kmlId.
 * @param {string} kmlId String id of a kml entry.
 * @return {number} Entry id (index in the array).
 * @private
 */
earth.outreach.Showcase.prototype.findEntryIdInCurrent_ = function(kmlId) {
  kmlId = unescape(kmlId);
  for (var i = 0, size = this.entries.length; i < size; i++) {
    var currId = unescape(this.createEntryId_(this.entries[i]['title']));
    if (currId == kmlId) return i;
  }
};


/**
 * Searches feed for any entries which have a matching title.
 * @param {string} title Title of the kml entry.
 * @private
 */
earth.outreach.Showcase.prototype.findEntryIdInFeed_ = function(title) {
  this.searched = true;
  title = title.replace(/_/g, ' ');
  this.quickLink(title);
};


/**
 * Pulls entries form the gallery feed starting at the specified index.
 * @param {number} startIndex Gallery start position. Needed because
 *    gallery can display only 100 entries at the time.
 */
earth.outreach.Showcase.prototype.getGalleryEntries = function(startIndex) {
  this.gfeed = new google.feeds.Feed('http://www.google.com/gadgets/' +
                                     'directory?synd=earth&cat=outreach' +
                                     '&output=rss&start=' + startIndex +
                                     '&num=' + this.NUM_ENTRIES);
  this.gfeed.setNumEntries(this.NUM_ENTRIES);
  this.gfeed.setResultFormat(google.feeds.Feed.XML_FORMAT);
  this.gfeed.load(this.parseGData_);
};


/**
 * Hides or shows loading icon.
 * @param {bool} hide If true - hide image; else - show image.
 * @private
 */
earth.outreach.Showcase.prototype.hideLoadingImage_ = function(hide) {
  if (hide) {
    this.loadingImg.className = 'hidden';
  } else {
    this.loadingImg.className = '';
  }
};


/**
 * Extracts data from xml gallery feed and puts it into entries object.
 * @param {Object} gdata Gallery feed data.
 * @private
 */
earth.outreach.Showcase.prototype.parseGData_ = function(gdata) {
  var cache = true;

  if (!gdata.error) {
    var items = gdata.xmlDocument.getElementsByTagName('item');
    for (var i = 0, size = items.length; i < size; i++) {
      var entry = {};

      for (var j = 0, s = items[i].childNodes.length; j < s; j++) {
        var node = items[i].childNodes[j];
        if (node.firstChild) {
          entry[node.nodeName] = node.firstChild.nodeValue;
        } else {
          entry[node.nodeName] = '';
        }
      }

      earth.outreach.showcase.entries.push(entry);
    }
  }

  var feedUrl = 'http://spreadsheets.google.com/feeds/' +
                  'list/pcO-d8z1IPLqsz2YITMfdOg/default/' +
                  'public/basic'
  gweb.feed.loadSpreadsheet(earth.outreach.showcase.parseSpreadsheetData_,
                            feedUrl, cache);
};


/**
 * Extracts data from the auxilary spreadsheet and puts it into entries object.
 * @param {Object} data Spreadsheet feed data.
 * @private
 */
earth.outreach.Showcase.prototype.parseSpreadsheetData_ = function(data) {
  for (var i = 0, size = data.length; i < size; i++) {
    var item = data[i];
    for (var j = 0; j < earth.outreach.showcase.entries.length; j++) {
      if (item['rowTitle'] ==
          earth.outreach.showcase.entries[j]['gadgets:alternate_url']) {
        for (var elem in item) {
          earth.outreach.showcase.entries[j][elem] = item[elem];
        }
      }
    }
  }

  if (earth.outreach.showcase.params['kml'] && location.hash != '') {
    earth.outreach.showcase.showDetails('',
        earth.outreach.showcase.findEntryIdInCurrent_(
        earth.outreach.showcase.params['kml']),
        earth.outreach.showcase.params['kml']);
  } else {
    earth.outreach.showcase.showEntries();
  }
};


/**
 * Exectues quick link action.
 * @param {string} query Query associated with the quick link.
 */
earth.outreach.Showcase.prototype.quickLink = function(query) {
  query = query.replace(/\s/g, '+');
  var cat = 'outreach';
  if (query) {
    cat += ':' + query;
  }
  this.hideLoadingImage_(false);
  this.start = 0;
  this.entries = [];

  var queryUrl = 'http://www.google.com/gadgets/directory?synd=earth' +
                 '&cat=' + cat + '&preview=on&output=rss&&num=' +
                 this.NUM_ENTRIES;

  gfeed = new google.feeds.Feed(queryUrl);

  gfeed.setNumEntries(this.NUM_ENTRIES);
  gfeed.setResultFormat(google.feeds.Feed.XML_FORMAT);
  gfeed.load(this.parseGData_);
};


/**
 * Processes the searchbox value and searches for the KML.
 */
earth.outreach.Showcase.prototype.processSearch = function() {
  var query = document.getElementsByName('search')[0].value;
  query = query.replace(/\s/g, '+');
  location.hash = '#';
  this.search(query);
};


/**
 * Queries Earth gallery and returns the results.
 * @param {string} query The string to search.
 */
earth.outreach.Showcase.prototype.search = function(query) {
  this.hideLoadingImage_(false);
  this.start = 0;
  this.entries = [];

  var queryUrl = 'http://www.google.com/gadgets/directory?synd=earth' +
                 '&cat=outreach&preview=on&output=rss&num=' +
                 this.NUM_ENTRIES + '&q=' + query;

  gfeed = new google.feeds.Feed(queryUrl);
  gfeed.setNumEntries(this.NUM_ENTRIES);
  gfeed.setResultFormat(google.feeds.Feed.XML_FORMAT);
  gfeed.load(this.parseGData_);
};



/**
 * Displays details of the selected entry.
 * @param {Event} e Event handler.
 * @param {string} linkId Number identified of the selected entry.
 * @param {string} kmlId Unique string identified of the selected entry.
 */
earth.outreach.Showcase.prototype.showDetails = function(e, linkId, kmlId) {
  this.hideLoadingImage_(true);

  this.media.className = 'hidden';
  this.details.className = 'showcase-details';

  var descr = document.getElementById('showcase-details-description');
  var title = document.getElementById('showcase-details-title');
  var author = document.getElementById('showcase-details-author');
  var caseStudy = document.getElementById('showcase-details-casestudy');
  var image = document.getElementById('showcase-details-image');
  var kmzLink = document.getElementById('showcase-details-kmz');
  var apiSizeLink = document.getElementById('showcase-size');
  var youtube = document.getElementById('showcase-details-youtube');
  var kmlInfo = document.getElementById('showcase-details-kmlinfo');
  var kmlTour = document.getElementById('showcase-details-kmltour');
  var impact = document.getElementById('showcase-details-impact');
  var skills = document.getElementById('showcase-details-skills');
  var tutorials = document.getElementById('showcase-details-tutorials');

  if (kmlId) {
    var entryId = this.findEntryIdInCurrent_(kmlId);
    if (!entryId && entryId != 0 && !this.searched) {
      entryId = this.findEntryIdInFeed_(kmlId);
      return;
    }
  } else {
    var entryId = linkId;
  }

  // Don't continue if title not found in the current entries set.
  if (!entryId && entryId != 0) {
    this.breaksearch = true;
    this.showEntries();
    return;
  }

  var kml = this.entries[entryId];
  var kmlUrl = kml['gadgets:alternate_url'];
  location.hash = '#kml=' + this.createEntryId_(kml['title']);

  apiSizeLink.className = 'showcase-apisize';

  // Make sure enlarged api window goes below the text.
  if (apiSizeLink.name == 'shrink') {
    this.earthapi.style.clear = 'both';
  }

  // Display all details
  title.innerHTML = kml['title'];
  descr.innerHTML = this.createSnippetSentence_(kml['description']);
  author.innerHTML = kml['author'];

  if (kml['mapsapilink']) {
    kmzLink.innerHTML = '<a href="' + kml['mapsapilink'] + '" ' +
        'target="_blank">Visit the website to view the map</a>';
  } else {
    kmzLink.innerHTML = '<a href="' + kmlUrl + '">' +
        'Download KML file to view in Google Earth</a>';
  }

  // Display auxilary details.
  if (kml['kmltour']) {
    kmlTour.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = '<a href="' + kml['kmltour'] + '">' +
        'Download KML tour</a>';
    kmlTour.appendChild(container);
  } else {
    kmlTour.innerHTML = '';
  }

  if (kml['casestudy']) {
    caseStudy.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = '<a href="' + kml['casestudy'] + '">' +
        'See the case study</a>';
    caseStudy.appendChild(container);
  } else {
    caseStudy.innerHTML = '';
  }

  if (kml['kmlinformation']) {
    kmlInfo.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = kml['kmlinformation'];
    kmlInfo.appendChild(container)
  } else {
    kmlInfo.innerHTML = '';
  }

  if (kml['impact']) {
    impact.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = kml['impact'];
    impact.appendChild(container)
  } else {
    impact.innerHTML = '';
  }

  if (kml['skills']) {
    skills.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = kml['skills'];
    skills.appendChild(container);
  } else {
    skills.innerHTML = '';
  }

  if (kml['tutorials']) {
    tutorials.innerHTML = '';
    var container = document.createElement('div');
    container.innerHTML = 'Tutorials: ' + kml['tutorials'];
    tutorials.appendChild(container);
  } else {
    tutorials.innerHTML = '';
  }

  if (kml['youtube']) {
    youtube.innerHTML = '<object type="application/x-shockwave-flash"' +
        'style="width:300px; height:243px;"' +
        'data="http://www.youtube.com/v/' + kml['youtube'] + '&rel=0">' +
        '<param name="movie" value="http://www.youtube.com/v/' +
        kml['youtube'] + '&rel=0" /></object>';
  } else {
    youtube.innerHTML = '';
  }

  // Replace earth api with maps api image if present.
  if (!kml['mapsapiimage']) {
    image.innerHTML = '';
    apiSizeLink.className = 'showcase-apisize';
    earth.earthapi.loadKML(kmlUrl);
    this.earthapi.style.height = '400px';
  } else {
    this.earthapi.style.height = '0px';
    apiSizeLink.className = 'hidden';
    if (kml['mapsapilink']) {
      image.innerHTML = '';
      var container = document.createElement('div');
      container.innerHTML = '<a href="' + kml['mapsapilink'] + '" ' +
          'target="_blank"><img src="' + kml['mapsapiimage'] + '" /></a>';
      image.appendChild(container);
    } else {
      image.innerHTML = '<img src="' + kml['mapsapiimage'] + '" />';
    }
  }

  this.createDetailsNavigation_(linkId);
};


/**
 * Shows kml entries using data extracted from the feed.
 */
earth.outreach.Showcase.prototype.showEntries = function() {
  var apiSizeLink = document.getElementById('showcase-size');
  var mapImage = document.getElementById('showcase-details-image');
  var entry = '';
  var showcaseDisplay = '<table>';
  var size = this.entries.length;

  // Hide details page and reset hash
  this.media.className = '';
  this.details.className = 'hidden';
  this.earthapi.style.height = '0px';
  mapImage.innerHTML = '';
  this.earthapi.style.clear = '';
  apiSizeLink.className = 'hidden';
  this.toggleNav_('back', 'hidden');

  // Create the table with the entries.
  for (var i = this.start; i < this.start + this.NUM_DISP && i < size; i++) {
    var kmlId = this.createEntryId_(this.entries[i]['title']);
    if (i % 2 == 0) {
      showcaseDisplay += '<tr>';
    }
    showcaseDisplay += '<td width="50%">'
    var entry = '<table class="showcase"><tbody><tr><td>' +
        ' <a href="#kml=' + kmlId + '" name="' + i + '"' +
        ' onclick="earth.outreach.showcase.showDetails(event, this.name, \'' +
        kmlId + '\');">' +
        '<img class="showcase-thumb" src="' +
        this.entries[i]['gadgets:thumbnail'] + '" /></a>' + '<td><b>' +
        this.entries[i]['title'] + '</b>' + '<p>' +
        this.createSnippet_(this.entries[i]['description'], this.SNIP_LEN) +
        ' <a href="#kml=' + kmlId + '" name="' + i + '"' +
        ' onclick="earth.outreach.showcase.showDetails(event, this.name, \'' +
        kmlId + '\');">' +
        'Learn more</a></p></td></tr></tbody></table>';
    showcaseDisplay += entry + '</td>';

    // Two columns per row - start new row.
    if (i % 2 == 1) {
      showcaseDisplay += '</tr>';
    }
  }
  showcaseDisplay += '</table>';
  this.content.innerHTML = showcaseDisplay;

  this.showNav_(size);
  this.createNavigation_();
  this.showMessage_(size);
  this.hideLoadingImage_(true);
};


/**
 * Shows "kml entries not found" message.
 * @param {number} size Amount of found KML entries.
 * @private
 */
earth.outreach.Showcase.prototype.showMessage_ = function(size) {
  if (!size) {
    this.message.className = 'showcase-results';
    this.content.className = 'hidden';
    this.toggleNav_('prev', 'hidden');
    this.toggleNav_('next', 'hidden');
  } else {
    this.message.className = 'hidden';
    this.content.className = 'showcase-results';
  }
};


/**
 * Controls the display of next/prev navigation.
 * @param {int} size Number of entries to display.
 * @private
 */
earth.outreach.Showcase.prototype.showNav_ = function(size) {
  if (size <= this.NUM_DISP) {
    // No nav links: number of entries doesn't warrant showing any scrolling
    this.toggleNav_('prev', 'hidden');
    this.toggleNav_('next', 'hidden');
  } else if (this.start + this.NUM_DISP >= size) {
    // No next link: displaying the last set of entries
    this.toggleNav_('prev', '');
    this.toggleNav_('next', 'hidden');
  } else if (this.start < this.NUM_DISP) {
    // No prev link: displaying the first set of entries
    this.toggleNav_('prev', 'hidden');
    this.toggleNav_('next', '');
  } else {
    // Show both links
    this.toggleNav_('next', '');
    this.toggleNav_('prev', '');
  }
};


/**
 * Shows or hides specified nav link.
 * @param {string} dir Identifies which link to hide. values: prev, next.
 * @param {string} action Identifies whether link should be shown or hidden.
 * @private
 */
earth.outreach.Showcase.prototype.toggleNav_ = function(dir, action) {
  var nav = document.getElementById('showcase-' + dir);
  nav.style.visibility = action;
};
