/* This file has all the tools for the explorer in the popup player and on the
 * homepage for radiolab. The popup player stuff is done in an unobtrusive
 * manner as possible so player development for other sites doesn't have to
 * worry about the explorer. */

var setExploreList = null;

var ZIPPER_SCROLL = 3;

$(function() {
  if ("undefined" != typeof inPopupPlayer && inPopupPlayer) {
    setExploreList = popupSetExploreList;
    addExplore();
    rearrangePopupPlayer();
    explorerPlaylist = new Playlist();
  } else {
    var filterContainer = $(".explore-form-homepage form");
    if (filterContainer.length) {
      setExploreList = homepageSetExploreList;
      loadExploreDataAndFilters(filterContainer);
    }
  }
});

var zipperCarousel = null;

function zipperInitCallback(carousel) {
  zipperCarousel = carousel;

  $(".zipper-previous, .zipper-nav .prev").click(function(evt) {
    evt.preventDefault();
    zipperJumpToPage(zipperPage() - 1);
  });

  $(".zipper-next, .zipper-nav .next").click(function(evt) {
    evt.preventDefault();
    zipperJumpToPage(zipperPage() + 1);
  });
}

function zipperPage() {
  return 1 + (zipperCarousel.first - 1) / ZIPPER_SCROLL;
}

function addExplore() {
  var id = "explore";
  var newTab = $("<li/>").addClass("tab").addClass(id);
  var tabs = $(".tab");
  newTab.insertAfter($(tabs[tabs.length - 1]));

  var explorePanel = $("<div/>").attr("id", id).addClass("hide");
  explorePanel.addClass("tab_panel").appendTo($(".playlists"));
  var filterWrapper = $("<div/>").addClass("explore-form-popup");
  filterWrapper.addClass("explore-form").appendTo(explorePanel);
  var filterContainer = $("<form/>").attr("action", "#");
  filterContainer.appendTo(filterWrapper);
  filterContainer.html("<img src='/media/img/loading.gif' alt='Loading' />");

  var a = $("<a/>").attr("href", "#").appendTo(newTab).html("Explore");
  a.click(function(evt) {
    evt.preventDefault();
    showHelper(id);
  });
  $(".tab a").click(function() {
    fixDescriptionHeights();
  });
  var css = "popup_explore_filterContainer";
  loadExploreDataAndFilters(filterContainer, function() {
    explorer.playlist = $("<ul/>").addClass("playlist");
    explorer.playlist.attr("id", "explorePlaylist").appendTo(explorePanel);
  });
}

DESCRIPTION_HEIGHT = 30;

/* truncateToHeight doesn't work when the element in question is not
 * visible. Hence, actually truncate when we show the explore tab,
 * and when we create the description html. */
function fixDescriptionHeights() {
  $(".description").truncateToHeight(DESCRIPTION_HEIGHT);
}

var explorer = null;
function loadExploreDataAndFilters(filterContainer, callback) {
  $.getJSON("/api/explore_data/radiolab/", {}, function(data, status) {
    explorer = data;
    for (var storyI = 0; storyI < explorer.stories.length; storyI++) {
      var story = explorer.stories[storyI];
      story.newsdate = dateFromString(story.newsdate);
    }
    filterContainer.empty();
    var typeColumn = newFilterGroup(filterContainer,
                                    "Explore Audio",
                                    "explore-radio");
    explorer.allTypes = appendRadioButton(
      typeColumn,
      "All",
      "",
      "type",
      true,
      setExploreList);
    explorer.typeInputs = [];
    for (var type_i = 0; type_i < explorer.types.length; type_i++) {
      var type = explorer.types[type_i];
      explorer.typeInputs.push(appendRadioButton(
        typeColumn,
        type.plural,
        type.singular,
        "type",
        false,
        setExploreList));
    }
    $("input[name='type']").parent().parent().buttonset();

    var tagColumn = newFilterGroup(filterContainer,
                                   "Explore by Tags",
                                   "tags-checkbox");
    explorer.tagInputs = [];
    var tagset = null;
    for (var tag_i = 0; tag_i < explorer.tags.length; tag_i++) {
      var tag = explorer.tags[tag_i];
      if (0 == tag_i % 4) {
        tagset = $("<div/>").addClass("tagset").appendTo(tagColumn);
      }
      explorer.tagInputs.push(appendCheckbox(
        tagset,
        tag.substring(0, 1).toUpperCase() + tag.substring(1, tag.length),
        tag));
        $('.tags-checkbox input').button();
    }
    var sortColumn = newFilterGroup(filterContainer, "Sort by", "sort-by");
    function appendSort(by, selected) {
      return appendRadioButton(
        sortColumn,
        by,
        by.replace("Most ", "").toLowerCase(),
        "sort",
        selected,
        sortStories);
    }
    explorer.latest = appendSort("Latest", true);
    explorer.comments = appendSort("Most Comments", false);
    explorer.likes = appendSort("Most Liked", false);
    $("input[name='sort']").parent().parent().buttonset();
    if (callback) {
      callback();
    }
    sortStories();
  });
}

function sortStories() {
  var sortBy = "newsdate";
  if (explorer.comments.attr("checked")) {
    sortBy = "comments";
  } else if (explorer.likes.attr("checked")) {
    sortBy = "likes";
  }
  explorer.stories.sort(function(left, right) {
    return compareStories(left, right, sortBy);
  });
  setExploreList();
}

function compareStories(left, right, sortBy) {
  var firstCompare = right[sortBy] - left[sortBy];
  if (firstCompare != 0) {
    return firstCompare;
  } else if (isType(left, "episode") && !isType(right, "episode")) {
    return -1;
  } else if (!isType(left, "episode") && isType(right, "episode")) {
    return 1;
  } else if (isType(left, "segment") && !isType(right, "segment")) {
    return -1;
  } else if (!isType(left, "segment") && isType(right, "segment")) {
    return 1;
  } else if (isType(left, "segment") && isType(right, "segment")) {
    return left.segment_number - right.segment_number;
  }
  return 0;
}

function replaceFirstWithPodcast(stories) {
  var foundPodcast = false;
  for (var storyI = 0;
       storyI < explorer.stories.length && !foundPodcast;
       storyI++) {
    var story = explorer.stories[storyI];
    if (isType(story, "podcast")) {
      stories[0] = story;
      foundPodcast = true;
    }
  }
}

function isType(story, type) {
  for (typeI in story.types) {
    if (type == story.types[typeI]) {
      return true;
    }
  }
}

function explorerItemHelper(templateCss, story) {
  var template = $("." + templateCss);
  var item = template.clone().removeClass(templateCss);
  item = item.appendTo(template.parent()).autoRender(story);
  if (!story.canDownload) {
    item.find(".download").remove();
  }
  if (!story.topExploreImage) {
    item.find("img").remove();
  }
  return item;
}

var firstTimeHomepage = true;
var zipperStories = [];
function homepageSetExploreList() {
  zipperStories = getFirstXStories();
  if (firstTimeHomepage) {
    firstTimeHomepage = false;
    replaceFirstWithPodcast(zipperStories);
  }
  for (var storyI = 0; storyI < zipperStories.length; storyI++) {
    var story = zipperStories[storyI];
    story.addJavascript = "return addAudioFromUrl('" + story.xspf + "');";
    story.playJavascript = "return listenAudioFromUrl('" + story.xspf + "');";
  }
  var topExplore = $(".explore_wrapper").empty();
  if (zipperStories.length) {
    var item = explorerItemHelper("explore_template", zipperStories[0]);
    topExplore.append(item);
    zipperStories.shift();
  }
  if (zipperCarousel) {
    zipperCarousel.reset();
  } else {
    $(".zipper-items").jcarousel({
      scroll: ZIPPER_SCROLL,
      initCallback: zipperInitCallback,
      buttonNextHTML: null,
      buttonNextHTML: null,
      itemLoadCallback: zipperItemLoadCallback,
      itemFallbackDimension: 620
    });
    window.setTimeout(loadZipperItemsBackup, 100);
  }
}

var initiallyLoaded = false;
function loadZipperItemsBackup() {
  /* Go to page 2 of the zipper, reload the page. Chrome usually doesn't fire
   * the init, and even when it does it takes too long to happen. */
  if (!initiallyLoaded) {
    if (zipperCarousel) {
      zipperCarousel.reset();
    } else {
      window.setTimeout(loadZipperItemsBackup, 100);
    }
  }
}

function zipperJumpToPage(page) {
  var from = 1 + ZIPPER_SCROLL * (page - 1);
  // .has is 0 based, .scroll is 1 based.
  loadZipperItems(from - 1, from + ZIPPER_SCROLL - 1);
  zipperCarousel.scroll(from);
  updateZipperNavigation();
}

function loadZipperItems(from, to) {
  for (var i = from; i <= to; i++) {
    if (!zipperCarousel.has(i) && i < zipperStories.length) {
      var item = explorerItemHelper("zipper_template", zipperStories[i]);
      item.find(".description").addClass("not_truncated");
      zipperCarousel.add(i, item.html());
      item.remove();
    }
  }
  $(".not_truncated").each(function() {
    var me = $(this).removeClass("not_truncated");
    var parnt = me.parents(".zipper-content");
    var h2 = parnt.find("h2");
    me.truncateToHeight(parnt.height() - h2.outerHeight());
  });
}

function zipperItemLoadCallback(carousel, state) {
  if ('init' == state) {
    initiallyLoaded = true;
    zipperJumpToPage(1);
  }
}

function updateZipperNavigation() {
  var nav = $(".zipper-nav");
  if (zipperStories.length <= ZIPPER_SCROLL) {
    nav.hide();
  } else {
    nav.show()
  }
  var prevs = $(".zipper-previous, .zipper-nav .prev");
  if (zipperCarousel.first == 1) {
    prevs.hide();
  } else {
    prevs.show()
  }
  var nexts = $(".zipper-next, .zipper-nav .next");
  if (zipperStories.length <= 0 ||
      (zipperCarousel.first <= zipperStories.length &&
       zipperStories.length <= zipperCarousel.last)) {
    nexts.hide();
  } else {
    nexts.show();
  }
  setZipperPaging(1 + (zipperCarousel.first - 1) / ZIPPER_SCROLL);
}

function setZipperPaging(pageNumber) {
  var nav = $(".zipper-nav");
  nav.find(".page").remove();
  var pages = [];
  var maxPages = Math.ceil(zipperStories.length / ZIPPER_SCROLL);
  var from = pageNumber - 2;
  var to = pageNumber + 2;
  for (var i = from; i <= to; i++) {
    if (1 <= i && i <= maxPages) {
      pages.push(i);
    }
  }
  if (from == 2) {
    pages = [1].concat(pages);
  } else if (from > 2) {
    pages = [1, false].concat(pages);
  }
  if (to == maxPages - 1) {
    pages.push(maxPages);
  } else if (to < maxPages - 1) {
    pages = pages.concat([false, maxPages]);
  }
  for (var pageI = 0; pageI < pages.length; pageI++) {
    var page = pages[pageI];
    var li = $("<li/>").addClass("page").appendTo(nav);
    if (page) {
      li.append($("<a/>").attr("href", "#").text(page).click(function(evt) {
        evt.preventDefault();
        zipperJumpToPage($(this).text());
      }));
      if (page == pageNumber) {
        li.addClass("current");
      }
    } else {
      li.text("...");
    }
  }
  nav.find(".next").appendTo(nav);
}

var explorerPlaylist = null;
function popupSetExploreList() {
  explorer.playlist.empty();
  var stories = getFirstXStories(10);
  explorerPlaylist.clear(true);
  for (var storyI = 0; storyI < stories.length; storyI++) {
    createAudioFileElement(stories[storyI], false).appendTo(explorer.playlist);
    explorerPlaylist.linkAudioFile(stories[storyI], true);
  }
  fixDescriptionHeights();
}

function getFirstXStories(x) {
  var returnList = [];
  var storyI = 0;
  var found = 0;
  while (storyI < explorer.stories.length && (!x || found < x)) {
    var story = explorer.stories[storyI];
    var typesMatch = matchHelper(explorer.typeInputs, story.types);
    if (explorer.allTypes.attr("checked") || typesMatch) {
      var tags = checkedInputs(explorer.tagInputs);
      if (tags.length == 0 || matchHelper(tags, story.tags)) {
        found++;
        returnList.push(story);
      }
    }
    storyI++;
  }
  return returnList;
}

function matchHelper(inputList, lookIn) {
  inputList = checkedInputs(inputList);
  for (var i = 0; i < inputList.length; i++) {
    for (var j = 0; j < lookIn.length; j++) {
      if (lookIn[j] == inputList[i].attr("value")) {
        return true;
      }
    }
  }
  return false;
}

function checkedInputs(inputList) {
  var returnValue = [];
  for (var i = 0; i < inputList.length; i++) {
    var input = inputList[i];
    if (input.attr("checked")) {
      returnValue.push(input);
    }
  }
  return returnValue;
}

function newFilterGroup(filterGroups, title, css) {
  var group = $("<fieldset/>").appendTo(filterGroups).addClass(css);
  group.append($("<h3/>").html(title + ":"));
  return group;
}

function appendRadioButton(wrapper, display, value, group, checked, change) {
  var input = $("<input type='radio' />").attr("name", group).change(change);
  // Sigh.
  if ($.browser.msie && $.browser.version == "7.0") {
    input.click(function() {
      $("input[name='" + input.attr("name") + "']").attr("checked", false);
      input.attr("checked", true);
      change();
    });
  }
  input = appendHelper(wrapper, display, value, group + "_" + value, input);
  if (checked) {
    input.attr("checked", true);
  }
  return input;
}

function appendCheckbox(wrapper, display, value) {
  var input = $("<input type='checkbox' />").change(setExploreList);
  return appendHelper(wrapper, display, value, value, input);
}

function appendHelper(wrapper, display, value, id, input) {
  var span = $("<span/>").appendTo(wrapper);
  input.attr("value", value).attr("id", id).appendTo(span);
  var label = $("<label/>").attr("for", id).text(display).appendTo(span);
  return input;
}

function rearrangePopupPlayer() {
  var topTabRow = $("<ul/>").insertBefore($(".tabs"));
  topTabRow.addClass("tabs").addClass("top_tabs").addClass("my_playlist");
  $(".clear_playlist").detach().appendTo(topTabRow);
  // Firefox and Chrome don't respect window.close when there isn't an opener.
  if (window.opener) {
    var closeA = $("<a/>").attr("href", "#").html("Close");
    closeA.click(function(evt) {
      evt.preventDefault();
      window.close();
    });
    $("<li/>").addClass("close").append(closeA).appendTo(topTabRow);
  }
  
  $("#audio-help").detach().insertAfter($(".outer_player"));
}

function fillAudioFileElement(newAudioFile,
                              tr,
                              title,
                              dateStr,
                              playThis,
                              inMyPlaylist) {
  appendAudioFileImage(newAudioFile, tr);
  var td = tdAfterImage(tr, newAudioFile).addClass("center_cell");
  $("<div/>").addClass("title").strippedHtml(title).appendTo(td);
  var description = $("<div/>").addClass("description").appendTo(td);
  td = $("<td/>").addClass("action_cell").appendTo(tr);
  if (inMyPlaylist) {
    addRemove($("<div/>").addClass("remove").appendTo(td), newAudioFile);
  } else {
    addAddToPlaylist($("<div/>").addClass("add").appendTo(td), newAudioFile);
  }
  var actions = $("<ul/>").addClass("actions").appendTo(td);
  appendPlay(playThis, actions);
  appendDownload(newAudioFile, actions);
  description.truncateToHeight(DESCRIPTION_HEIGHT, newAudioFile.description);
}

