// protected namespace
(function () {

var details        = false;
var details_loaded = false;
var $ts            = null;
var thumbs_loading = 0;
var lowest_page    = 1;
var highest_page   = 1;
var scroll_page    = 1;

function showDetails() {
  if (details_loaded) {
    $('#details').show('fast');
  }
  else {
    $('#details-spinner').show();
    $('#details').load(details_url, null, function () {
      $('#details').show('fast', function () {
        $('#details-spinner').hide();
      });
    });    
  }

  details = details_loaded = true;
  $('#toggle-details').text('hide details');
  $.cookie('show_details', 1, { path: '/' });
}

function setThumbsContainerHeight() {
  var bh = window.innerHeight || document.documentElement.clientHeight;
  $('#thumbs').height(bh - 45);
  $ts.height(bh - 75);
}

function ajaxPageLink(url) {
  var m;
  if ((m = url.replace(/#.*/, '').match(/(.+)([?&])page=(\d+)(.*)/)))
    return m[1] + (m[4] ? m[2] + m[4] : '') + '#page=' + m[3];
  else
    return url;
}

function doScrolling() {
  var ts        = $ts[0];
  var scrollTop = $ts.scrollTop();
  var load_page, prepend;

  if ((scrollTop + $ts.height()) / ts.scrollHeight > 0.9
      && highest_page < num_pages && scrollTop > prev_scrollTop) {
    load_page = highest_page + 1;
  }
  else if (scrollTop / ts.scrollHeight < 0.1
            && lowest_page > 1 && scrollTop < prev_scrollTop) {
    prepend = true;
    load_page = lowest_page - 1;
  }

  prev_scrollTop = scrollTop;
  if (!load_page) return;

  if (prepend) $ts.prepend(loadingDiv());
  else         $ts.append(loadingDiv());

  loadThumbs(load_page, prepend, true);
}

function loadingDiv() {
  return '<div id="thumbs-loading">Loading thumbnails...</div>';
}

function loadThumbs(page, prepend, again, prev, scroll_mid) {
  thumbs_loading++;

  var ts = $ts[0];

  var url = (prev_page || next_page)
    .replace(/#.*/, '').replace(/page=\d+/, 'page=' + page) + '&frag=1';
  if (prev) url += '&prev=1';

  $.get(url, null, function (html) {
    $('#thumbs-loading').remove();
    if (!html) return;

    if (prepend) {
      $ts.prepend(html);
      lowest_page--;
    }
    else {
      $ts.append(html);
      highest_page++;
    }

    if (scroll_mid) {
      $ts.scrollTop(Math.round(ts.scrollHeight / 2));
      fixPageHash();
    }

    if (again) doScrolling(); // we might need to go again
    thumbs_loading--;
  }, 'html');
}

function fixPageHash() {
  var px_per_page = Math.round($ts[0].scrollHeight / 
    (highest_page - lowest_page + 1));
  var new_page = Math.floor(
    ($ts.scrollTop() + Math.round($ts.height() / 2)) / px_per_page
  ) + lowest_page;
  if (new_page != scroll_page) {
    scroll_page = new_page;
    window.location.href = window.location.href.replace(/(#page=\d+)?$/,
      '#page=' + scroll_page);
  }
}

// onload init code
$(function () {
  var paging = 'undefined' != typeof num_pages && num_pages > 1;

  if (paging && $.cookie('disable_ascroll')) {
    $('#thumbscroll').remove();
    $('#paging-top').before(
      '<a href="#" id="enable-ascroll" title="Enable continuous scrolling">S</a>'
    );
    $('#enable-ascroll').click(function () {
      $.cookie('disable_ascroll', null, { path: '/' });
      var orig = window.location.href;
      var href = ajaxPageLink(orig);
      if (orig == href) window.location.reload();
      else window.location.href = href;
      return false;
    });
  }


  $('#toggle-details').click(function () {
    if (details) {
      $('#details').hide('fast');
      details = false;
      $(this).text('show details');
      $.cookie('show_details', null, { path: '/' });
    }
    else showDetails();

    return false;
  });

  if ($.cookie('show_details') && $('#details').length) showDetails();

  if (next_page || prev_page) $(document).keydown(function (e) {
    if (!/^(HTML|BODY)$/.test(e.target.tagName)) return true;

    if ($ts.length) {
      var dir;
      // page up
      if      (e.keyCode == 33) dir = -1;
      // page down
      else if (e.keyCode == 34) dir =  1;
      // end
      else if (e.keyCode == 35) dir =  2;
      // home
      else if (e.keyCode == 36) dir = -2;

      if (dir) { 
        var scrollTop    = $ts.scrollTop();
        var height       = $ts.height();
        var maxScroll    = $ts[0].scrollHeight - height;

        if ((dir < 0 && scrollTop > 0) || 
            (dir > 0 && scrollTop < maxScroll)) {

          // home/end
          if (Math.abs(dir) == 2) {
            $ts.scrollTop(dir < 0 ? 0 : maxScroll);
          }
          // page up/down
          else {
            // 170 = height of 1 row of context
            $ts.scrollTop(Math.min(maxScroll, Math.max(0, 
              scrollTop + dir * (height - 170)
            )));
          }
        }
        return false;
      }

    }
    else{
      // right arrow
      if (e.keyCode == 39 && next_page) {
        window.location.href = next_page;
        return false;
      }
      // left arrow
      else if (e.keyCode == 37 && prev_page) {
        window.location.href = prev_page;
        return false;
      }
    }

    return true;
  });

  $ts = $('#thumbscroll');
  if (paging && $ts.length) {
    var url = window.location.href;

    // if we're on a non-ajax page, redirect, yeah, lame, but easier
    var alink = ajaxPageLink(window.location.href);
    if (alink != window.location.href) window.location.href = alink;

    $('#paging-top').html(
      '<a id="disable-ascroll" href="#">Disable continuous scrolling</a>'
    );
    $('#disable-ascroll').click(function () {
      $.cookie('disable_ascroll', 1, { path: '/' });
      var href = window.location.href;
      var url  = href.replace(/#.*/, '');
      if (url == href) window.location.reload();
      else window.location.href = url;
      return false;
    });
    $('#paging-bottom').remove();

    // Get rid of the paging reference in the title
    $('title').text($('title').text().replace(/: Page [\d\/]+/, ''));
    setThumbsContainerHeight();
    $(window).resize(setThumbsContainerHeight);


    $('#thumbs .thumb').appendTo($ts);
    var m;
    if ((m = url.match(/#page=(\d+)/))) {
      var page = parseInt(m[1]);
      if (page > 1 && page <= num_pages) {
        scroll_page = page;
        if (page == 2) {
          $ts.prepend(loadingDiv());
          loadThumbs(page, false, false, false, true);
        }
        else {
          $ts.html(loadingDiv());
          loadThumbs(page, true, false, true, true);
        }
        lowest_page  = page - 1;
        highest_page = page;
      }
    }

    var prev_scrollTop = 0;
    if (num_pages > 1) {
      $ts.scroll(function (e) {
        fixPageHash();
        if (!thumbs_loading) doScrolling();
      });
    }
  }

  if (paging && !$.cookie('disable_ascroll')) {
    $('#index-link').click(function () {
      this.href = ajaxPageLink(this.href);
      return true;
    });
  }
});


})();
