(function($) {
  $.tnGallery = {
    main_pic_a:   function() { return $("article.main-pic a"); },
    main_pic:     function() { return $("article.main-pic img"); },
    list:         function() { return $("nav.gallery-thumbs ul"); },
    LIs:          function() { return $("li", this.list()); },

    select: function(li, url) {
      var $li = $(li);

      this.main_pic_a().attr("href", url);
      this.main_pic().hide().attr("src", url).fadeIn("slow");
      this.LIs().removeClass("current");
      $li.addClass("current");
    },

    hideLIs: function() {
      $("img", this.LIs()).css("visibility", "hidden");
    },

    update: function(li, photo) {
      $(li).
        find("a").
          attr("href", "#view" + photo.original).
          attr("rel", photo.original).end().
        find("img").
          attr("src", photo.icon).
          css("visibility", "visible");

      $(li).find("a").die().click(function() {
        $.tnGallery.activate(this);
      });
    },

    updatePrevLink: function($prev_link, prev_page) {
      var url = $prev_link.attr("href");

      if (prev_page) {
        $prev_link.css("visibility", "visible");
        $prev_link.attr("href", $.setQueryParam(url, "page", prev_page));
      } else {
        $prev_link.css("visibility", "hidden");
      }
    },


    updateNextLink: function($next_link, next_page) {
      var url = $next_link.attr("href");

      if (next_page) {
        $next_link.css("visibility", "visible");
        $next_link.attr("href", $.setQueryParam(url, "page", next_page));
      } else {
        $next_link.css("visibility", "hidden");
      }
    },

    activate: function(link) {
      var url = $(link).attr("href").replace(/^#view/, ""),
          $li = $(link).parents("li");

      $.tnGallery.select($li, url);
    }
  };

  $.fn.tnGalleryNav = function() {
    var $next_link = $("a.gallery-next", this),
        $prev_link = $("a.gallery-prev", this),
        $lis = $.tnGallery.LIs();

    function handleResponse(json) {
      var photos = json.photos,
          next_page = json.next_page;
          prev_page = json.prev_page;

      // Conditionally remove the link, or update the page parameter
      // depending on the value of `next_page`.
      $.tnGallery.updatePrevLink($prev_link, prev_page);
      $.tnGallery.updateNextLink($next_link, next_page);

      // Put the first photo result in the main_pic frame and mark it as
      // current.
      $.tnGallery.select($lis[0], photos[0].original);

      // Update the corresponding `photo` result to the
      // li'th element, i.e.
      //
      //   $lis[0] <- photos[0]
      //   $lis[1] <- photos[1]
      //
      // If photos[n] is null, the corresponding li is hidden.
      $.each($lis, function(i, li) {
        if (!photos[i]) {
          $(li).hide();
        } else {
          $(li).show();
          $.tnGallery.update(li, photos[i]);
        }
      });
    }

    $prev_link.live("click", function() {
      var url  = $prev_link.attr("href"),
          page = $.getQueryParam(url, "page");

      if (!page) { return false; }

      // By hiding the LIs, the spinners will automatically appear.
      $.tnGallery.hideLIs();

      // Issue a request to /event/:id/gallery.json?page=X
      $.getJSON(url, handleResponse);
      return false;
    });

    $next_link.live("click", function() {
      var url  = $next_link.attr("href"),
          page = $.getQueryParam(url, "page"),
          $lis = $.tnGallery.LIs();

      if (!page) { return false; }

      // By hiding the LIs, the spinners will automatically appear.
      $.tnGallery.hideLIs();

      // Issue a request to /event/:id/gallery.json?page=X
      $.getJSON(url, handleResponse);
      return false;
    });
  };

})(jQuery);
