// Copyright 2009 Google Inc.
// All Rights Reserved.
// Owner: webgroup-emea@google.com

/**
 * @fileoverview Javascript for Things to do.
 * @author amcgrath@google.com (Adam Mcgrath)
 */

/**
 * Namespace ttd (Things to do).
 */
var ttd = window.ttd || {};

/**
 * Creates a loader for use with Things to do landing page.
 * @constructor
 * @param {object} app_opts The application widgets options.
 * @param {object} ratings_opts The ratings widgets options.
 */
ttd.Loader = function(app_opts, ratings_opts) {
  this.app_opts = app_opts;
  this.ratings_opts = ratings_opts;
  this.ratings_loaded = false;
  this.api_loaded = false;
  if (this.ratings_opts) {
    this.appId = this.ratings_opts.appId || 76;
    this.loadRatingsApi_();
  }
};

/**
 * Loads the google annotaions api.
 * @private
 */
ttd.Loader.prototype.loadRatingsApi_ = function() {
  var devParam = this.ratings_opts.debug ? '&dev=1' : '';
  google.load('annotations', '1', {'other_params': 'appid=' + this.appId +
      '&hl=' + this.ratings_opts.lang + devParam,
      'callback': ttd.utils.bind(this.ratingsApiCallback, this)});
};

/**
 * Loads the ratings widget.
 * @private
 */
ttd.Loader.prototype.loadRatings_ = function() {
  if (!this.ttd_tips || !this.api_loaded) {
    return;
  }
  this.ratings_opts.count = this.ttd_tips.feed.entry.length;
  this.ratings_opts.callback = ttd.utils.bind(this.complete, this);
  this.ttd_ratings = new ttd.Ratings(this.ratings_opts);
};

/**
 * Once the loader is complete, loads the application.
 */
ttd.Loader.prototype.complete = function() {
  this.app_opts.ratings = this.ttd_ratings;
  this.app_opts.tipsData = this.ttd_tips;
  this.ttd_app = new ttd.App(this.app_opts);
};

/**
 * Handles the load of the google annotations api.
 */
ttd.Loader.prototype.ratingsApiCallback = function() {
  this.api_loaded = true;
  this.loadRatings_();
};

/**
 * Handles the load of the spreadsheet tips data.
 * @param {goog.annotations.entities} data The annotaions data.
 */
ttd.Loader.prototype.tipsCallback = function(data) {
  this.ttd_tips = data;
  if (this.ratings_opts) {
    this.loadRatings_();
  } else {
    this.complete();
  }
};

/**
 * Creates the application for use with Things to do landing page.
 * @constructor
 * @param {object} opts an object containing configuration properties.
 */
ttd.App = function(opts) {
  this.tipsContainer = document.getElementById(opts.tipsContainer);
  this.videoId = opts.videoId;
  this.tipId = opts.tipId;
  this.ratingsId = opts.ratingsId;
  this.ratings = opts.ratings;
  this.tipsData = opts.tipsData;
  this.defaultTip = opts.defaultTip || 3;
  this.tipHash = opts.tipHash || 'tip';
  this.tmplMain = opts.tmplMain;
  this.tmplVideo = opts.tmplVideo;
  this.tmplInput = opts.tmplInput;
  this.vidCls = opts.vidCls;
  this.schCls = opts.schCls;
  this.btnCls = opts.btnCls;
  this.currentTip = this.getCurrentTip();
  this.init_();
};

/**
 * Initiates the application.
 * @private
 */
ttd.App.prototype.init_ = function() {
  var re = /#tip([\d]+)/;
  var arr = this.ratings && this.ratings.getData() || this.tipsData.feed.entry;
  var html = '';
  for (var i = 0, len = arr.length; i < len; i++) {
    var count = this.ratings ? arr[i].entity.url.match(re)[1] - 1 : i;
    var tip = new ttd.Tip(this.tipsData.feed.entry[count], this.tmplInput);
    html += ttd.utils.templatize(tip, this.tmplMain);
  };
  this.tipsContainer.innerHTML = html;
  this.showTip(this.currentTip, true);
};

/**
 * @return {int} The id of the current tip.
 */
ttd.App.prototype.getCurrentTip = function() {
  var re = /#?tip([\d]{1,2})/;
  var match = document.location.hash.match(re);
  return match && match[1] || this.defaultTip;
};

/**
 * Creates the video object and displays it in the tip.
 * @param {int} id The id of the tip.
 * @private
 */
ttd.App.prototype.activateVideo_ = function(id) {
  var el = document.getElementById(this.videoId + id);
  var span = el.getElementsByTagName('span')[0];
  if (!span) {return;}
  var html = ttd.utils.templatize({'id': span.innerHTML}, this.tmplVideo);
  el.innerHTML = html;
};

/**
 * Gets the annotations widget, if available, and inserts it into the correct
 * and resets the entity to the correct value.
 * @param {int} id The id of the tip.
 * @private
 */
ttd.App.prototype.activateRating_ = function(id) {
  try {
    this.ratings.ratingsContainer.style.display = 'block';
    this.ratings.setEntity('#tip' + id);
    var ratingsDiv = document.getElementById(this.ratingsId + id);
    ratingsDiv.appendChild(this.ratings.getRatingsContainer());
  } catch (e) {
    // console.log(e);
  }
};

/**
 * Shows the tip, by number.
 * @param {int} id The id of the tip.
 * @param {boolean} isFirst Is this the first tip shown on page load.
 */
ttd.App.prototype.showTip = function(id, isFirst) {
  if ((id == this.currentTip || !document.getElementById(this.tipId + id)) &&
     !isFirst) {
   if (id == this.currentTip) {
     var tip = document.getElementById(this.tipId + id);
      ttd.utils.removeClass(tip, 'on');
      ttd.currentTip = 0;
   };
   return;
  };
  var oldTip = document.getElementById(this.tipId + this.currentTip);
  var newTip = document.getElementById(this.tipId + id);
  if (oldTip) {
   ttd.utils.removeClass(oldTip, 'on');
  };
  ttd.utils.addClass(newTip, 'on');
  this.activateVideo_(id);
  this.activateRating_(id);
  if (!isFirst && id > 5) {
   ttd.utils.updateLocationBar(id);
  };
  this.currentTip = id;
  this.showCount(id);
};

/**
 * If there is an instance of pageTracker available, track a tip view.
 * @param {int} id The id of the tip.
 */
ttd.App.prototype.showCount = function(id) {
  if (window['pageTracker']){
   pageTracker._trackPageview('/view/' + id);
  }
};

/**
 * If there is an instance of pageTracker available, track a tip actioned.
 * @param {int} id The id of the tip.
 * @return {boolean} Returns true to complete link.
 */
ttd.App.prototype.actionCount = function(id) {
  if (window['pageTracker']){
   pageTracker._trackPageview('/action/' + id);
  }
  return true;
};

/**
 * Represents a tip to be displayed.
 * @constructor
 * @param {google.feeds.entry} obj Tip data object.
 * @param {string} tmpl A template string.
 */
ttd.Tip = function(obj, tmpl) {
  this.tmpl = tmpl;
  this.obj = obj;
  this.count = this.getCount_();
  this.id = obj['gsx$number']['$t'];
  this.color = this.getColor_();
  this.desc = obj['gsx$description']['$t'];
  this.title = obj['gsx$title']['$t'];
  this.query = obj['gsx$search-query'] && obj['gsx$search-query']['$t'];
  this.fullurl = obj['gsx$url']['$t'];
  this.avatar = this.getAvatar_();
  this.user = obj['gsx$user'] && obj['gsx$user']['$t'];
  this.url = this.getUrl_();
  this.action = obj['gsx$action']['$t'];
  this.video = obj['gsx$video'] && obj['gsx$video']['$t'];
  this.className = this.getClassName_();
  this.inputs = this.query ? this.getInputsHtml_() : '';
};

/**
 * Holds the count for new tips.
 * @type {int}
 */
ttd.Tip.count = 0;

/**
 * Array of tips colors.
 * @type {array.<string>}
 */
ttd.Tip.COLORS = ['5FB7DF', '017DC3', 'ED6D6E', 'E50039', '726BAF',
                  'EC611E', 'F39907', '029D95', '51B948', 'E5007F'];

/**
 * Regex to grab key value pairs from url.
 * @type {regExp}
 */
ttd.Tip.PARAMSREGEX = /[\#|\?|\&](?:(.+?)=([^\#|^\?|^\&]+))/g;

/**
 * Regex to grab  url.
 * @type {regExp}
 */
ttd.Tip.URLREGEX = /^([^\#|^\?]+)/;

/**
 * @return {int} The current position of the tip.
 * @private
 */
ttd.Tip.prototype.getCount_ = function() {
  ttd.Tip.count++;
  return ttd.Tip.count;
};

/**
 * @return {string} The location of the avatar img.
 * @private
 */
ttd.Tip.prototype.getAvatar_ = function() {
  if (this.obj['gsx$avatar'] && this.obj['gsx$avatar']['$t']) {
     if (this.obj['gsx$avatar']['$t'] == 'none') {
       return 'no_pic.png';
     } else {
       return this.obj['gsx$avatar']['$t'];
     }
  } else {
    return 'no_pic.png';
  }
};

/**
 * @return {string} A HEX value for tips color.
 * @private
 */
ttd.Tip.prototype.getColor_ = function() {
  return ttd.Tip.COLORS[Math.floor(this.count % ttd.Tip.COLORS.length)];
};

/**
 * @return {string} The url for the action of the tip.
 * @param {string} url Tips url.
 * @private
 */
ttd.Tip.prototype.getUrl_ = function(url) {
  return this.query ? this.fullurl.match(ttd.Tip.URLREGEX)[1] : this.fullurl;
};

/**
 * @return {string} The class name for the tip.
 * @private
 */
ttd.Tip.prototype.getClassName_ = function() {
  // video form button
  var arr = ['tip'];
  if (this.video && !this.query) {arr.push('youtube')};
  if (this.query) {
    arr.push('search');
  } else if (this.action) {
    arr.push('button');
  };
  return arr.join(' ');
};

/**
 * @return {string} HTML for the tip's forms input.
 * @private
 */
ttd.Tip.prototype.getInputsHtml_ = function() {
  var inputsHtml = '';
  var that = this;
  this.fullurl.replace(ttd.Tip.PARAMSREGEX, function(match, key, value) {
      var obj = {
        key: key,
        value: value == '%s' ? that.query : value,
        type: value == '%s' ? 'text' : 'hidden'
      };
      inputsHtml += ttd.utils.templatize(obj, that.tmpl);
  });
  return inputsHtml;
};

