$(document).ready(function() {
  var entryNav = $("#portfolioEntryNav");
  $("#portfolioImages").scrollPanel(entryNav);
  $("#portfolioNav").scrollNavigation();
});

$.fn.scrollNavigation = function() {
  var list = $(this);
  var container = list.parent();
  var entries = list.find("li");
  
  var position = 0;
  var endPoint = 0;
  var travelling = false;
  
  // Store the widths
  var CONTAINER_WIDTH = container.width();
  var LIST_WIDTH      = entries.length * $(entries[0]).width();
  var OFFSET          = LIST_WIDTH - CONTAINER_WIDTH;
  list.css({width: LIST_WIDTH + "px"});
  
  // Dim the inactive elements
  var as = list.find("a:not(a[href$=" + window.location.pathname + "])");
  as.css({opacity: 0.35});
  as.hover(function() {
      $(this).css({opacity: 1});
    },
    function() {
      $(this).css({opacity: 0.35});
  });
  
  // Highlight the elements as the mouse hovers over

  // Finds an element's absolute position on the page and returns an object
  // with the left and top values.
  var findPosition = function(obj) {
    var left = 0;
    if (obj.offsetParent) {
      do {
        left += obj.offsetLeft;
      } while (obj = obj.offsetParent);
    }
    return left;
  };

  var move = function() {
    if (this.timeout) window.clearTimeout(this.timeout);
    if (position != endPoint) {
      travelling = true;
      // Determine the increment.
      var increment = Math.min(10, Math.abs(position - endPoint)*0.1);
      
      if (endPoint > position && position + increment < endPoint - 1) {
        position += increment;
      } 
      else if (position - increment > endPoint + 1) {
        position -= increment;
      }
      else {
        position = endPoint;
      }
      
      // move by that increment
      list.css({left: "-" + position + "px"});
      this.timeout = window.setTimeout(move, 30);
    }
    else {
      travelling = false;
    }
  };

  // Event handlers
  var mouseMove = function(e) {
    // Find the position of the mouse inside the container
    var mousePosition = e.pageX - findPosition(this);
    // Determine what proportion of the total it is
    var percentage = Math.min(1, Math.max((mousePosition-50) / (CONTAINER_WIDTH-100), 0));
    // Apply that proportion to the width of the list
    endPoint = Math.round(OFFSET * percentage);
    // Move to that point
    if (!travelling) move();
  };
  
  container.mousemove(mouseMove);
};

// Turns a pair of ULs into a scrolling panel and accompanying navigation 
// controls.
$.fn.scrollPanel = function(controls) {
  // Initialize everything
  var controls = $(controls);
  var anchors = controls.find("a");
  var currentIndex = 0;
  var currentAnchor = $(anchors[0]);
  var currentEntry = null;
  var PANEL_WIDTH = 562;
  var container = $(this);
  var entries = {};
  var mode = null;
  var totalNodes = null;
  
  // Initialises the entries, differentiating between the list and dl layouts
  var initEntries = function(nodes, setMode) {
    totalNodes = nodes.length - 1;
    mode = setMode;
    nodes.each(function(i, entry) {
      var entry = $(entry);
      // Set the current entry
      if (i == 0) {
        var opacity = 1;
        currentEntry = entry.attr("id");
      }
      else {
        var opacity = 0;
      }
      var position = i * PANEL_WIDTH;
      var control = controls.find("a[href*=" + entry.attr("id") + "]");
      if (mode == "dl") {
        var description = entry.next("dd");
        description.css({left: position + "px", opacity: opacity});
      }
      else {
        var description = null;
      }
      entry.css({left: position + "px"});
      entries[entry.attr("id")] = {position: position, count: i, anchor: control, description: description};
    });
  };
  
  // Differentiate between using a DL and a UL
  if (container.is("dl")) {
    initEntries(container.find("dt"), "dl");
  }
  else {
    initEntries(container.find("li"), "dl");
  }
  
  var moveTo = function(id) {
    var name = id.match(/#(\S+)/)[1];
    // Fade out the old and in wit the new
    if (mode == "dl") {
      entries[currentEntry].description.animate({opacity: 0}, 700);
      entries[name].description.animate({opacity: 1}, 1000);
    }
    container.animate({left: "-" + (entries[name].count * PANEL_WIDTH) + "px"}, 1200);
    // Update the displays and stuffies
    currentAnchor.removeClass("current");
    currentAnchor = entries[name].anchor;
    currentAnchor.addClass("current");
    currentIndex = entries[name].count;
    currentEntry = name;
    // Check to see if we need to hide overlay controls
    if (currentControl && (entries[name].count == 0 || entries[name].count == totalNodes)) {
      currentControl.removeClass("hover");
    }
  };
  
  // Add back and forward buttons
  var back = $('<a id="backControl">Back<span></span></a>');
  var forward = $('<a id="forwardControl">Forward<span></span></a>');
  container.after(back, forward);
  
  // Add the overlay
  container.before('<div id="overlay">&nbsp;</div>');
  
  // Event handlers
  var clickForward = function() {
    if (currentIndex < (anchors.length - 1)) {
      moveTo(anchors[currentIndex + 1].href);
    }
    return false;
  };
  var clickBackward = function() {
    if (currentIndex > 0) {
      moveTo(anchors[currentIndex - 1].href);
    }
    return false;
  };
  
  // Events for back and forward
  forward.click(clickForward);
  back.click(clickBackward);
  
  // Hover for back and forward
  var currentControl = null;
  var hoverOut = function() {
    currentControl.removeClass("hover");
    currentControl = null;
  };
  var forwardHoverIn = function() {
    currentControl = $(this);
    if (currentIndex < (anchors.length - 1)) currentControl.addClass("hover");
  };
  var backHoverIn = function() {
    currentControl = $(this);
    if (currentIndex > 0) currentControl.addClass("hover");
  };
  forward.hover(forwardHoverIn, hoverOut);
  back.hover(backHoverIn, hoverOut);
  
  // Attach the event handlers
  controls.click(function(e) {
    var target = $(e.target);
    if (target.is("a")) {
      moveTo(target.attr("href"));
      return false;
    }
  });
};