/*!
 * lightbox.next jQuery Plugin
 * http://csinaction.com/
 *
 * Copyright (c) 2009 Christoph Schiessl
 * Licenced under the MIT licence.
 */
(function($) {
  var images, currentImageIndex, prevImageIndex, nextImageIndex;
  var preload = {}, preloadPrev = new Image(), preloadNext = new Image();

  var win = $(window), ie6 = !window.XMLHttpRequest;
  var operaFix = window.opera && (document.compatMode == "CSS1Compat") && ($.browser.version >= 9.3);

  var overlayElement, containerElement, imageElement, captionElement, controlsElement;
  var playbackButtonElement, numberDisplayElement;
  var imageSelectorElement, imageSelectorSliderElement;

  var currentlyPlaying = false;

  $(function() {
		$("body").append(
			$([
        overlayElement = $('<div id="lbnOverlay"/>').click(closePlayer)[0],
        containerElement = $('<div id="lbnContainer"/>').click(closePlayer)[0]
			]).css("display", "none")
		);

    $(containerElement).append(
      $([
        imageElement = $('<div id="lbnImage" class="container"/>')[0],
        controlsElement = $('<div id="lbnControls" class="container"/>')[0]
      ])
    );

    $(imageElement).append(
      captionElement = $('<div id="lbnCaption"/>').hide()
    );


    $(controlsElement).append(
      $([
        playbackButtonElement = $('<a href="#" id="lbnPlaybackButton">&nbsp;</a>').click(playback)[0],
        numberDisplayElement = $('<div id="lbnNumberDisplay"/>')[0],
        imageSelectorElement = $('<div id="lbnImageSelector"/>').click(function() { return false; })[0]
      ])
    );

    $(imageSelectorElement).append(imageSelectorSliderElement = $('<div id="lbnImageSelectorSlider"/>'));
  });

  $.lightbox = function(filteredImages, startImageIndex) {
    images = filteredImages;

    windowWidth = operaFix ? document.documentElement.clientWidth : win.width();
    windowHeight = operaFix ? document.documentElement.clientHeight : win.height();

    $(containerElement).css({height: windowHeight, left: win.scrollLeft(), top: win.scrollTop()});

    // Magic numbers:
    // 20 = margin-top + margin-bottom
    // 64 = height of the controlsElement
    // 10 = border-top + border-bottom of the imageElement
    if (singleImageView()) { $(imageElement).css({height: windowHeight - 20}); }
    else { $(imageElement).css({height: windowHeight - 64 - 10 - 20}); }

    if (!singleImageView()) populateSlider(startImageIndex);

    setupKeyEvents();

    if (ie6 || (overlayElement.currentStyle && (overlayElement.currentStyle.position != "fixed"))) {
      overlayElement.style.position = "absolute";
      $(overlayElement).css({left: win.scrollLeft(), top: win.scrollTop(), width: windowWidth, height: windowHeight});
    }

    $(overlayElement).css("opacity", 0.9).show();
    $(containerElement).fadeIn(300);
    changeImage(startImageIndex);

    return false;
  };

  $.fn.lightbox = function(linkMapper, linksFilter) {
		var links = this;
    linkMapper = linkMapper || function() {
      previewImage = $("img", $(this))[0];
      return [$(this).attr("href"), previewImage ? previewImage.src : null, $(this).attr("title")];
    };
    linksFilter = linksFilter || function(element) {
      return (this == element) || (($(this).attr("rel").length > 3) && ($(this).attr("rel") == $(element).attr("rel")));
    };

		return links.unbind("click").click(function() {
			// Build the list of images that will be displayed
			var link = this, startIndex = 0, filteredLinks, i = 0, length;

			// find all links in the same set of links (same rel)
			filteredLinks = $.grep(links, function(el, i) {
				return linksFilter.call(link, el, i);
			});

			// find the index of the current link in the set
			for (length = filteredLinks.length; i < length; ++i) {
				if (filteredLinks[i] == link) startIndex = i;
				filteredLinks[i] = linkMapper.call(filteredLinks[i]);
			}

      // start the player with filtered list of links and the clicked thumbnail
      return $.lightbox(filteredLinks, startIndex);
	  });
  };

  function populateSlider(startImageIndex) {
    startImageIndex = startImageIndex || 0;
    for(i = 0;i < images.length;i++) {
      sliderElement = $('<img src="' + images[i][1] + '"/>');
      $(imageSelectorSliderElement).append(
        sliderElement.bind("click", i, function(event) {
        currentlyPlaying = false;
        $(containerElement).stopTime("lbn");
        $(playbackButtonElement).css("background-position", "0px 0px");
         return changeImage(event.data);
        })
      );
    }
    $(imageSelectorSliderElement).css("left", 360 - startImageIndex * 72);
    refreshNumberDisplay(startImageIndex);
  } // populateSlider

  function moveSlider(imageIndex) {
    $(imageSelectorSliderElement).animate({left: 360 - imageIndex * 72}, 500);
    refreshNumberDisplay(imageIndex);
  } // moveSlider

  function refreshNumberDisplay(imageIndex) {
    $(numberDisplayElement).html(imageIndex+1 + "/" + images.length);
  }

  function clearSlider() {
    $(imageSelectorSliderElement).empty();
  } // clearSlider

  function setupKeyEvents() {
    $(document).bind("keydown", function(event) {
      // Key Events regarding 'next', 'prev' and 'playback' make no sense for a single image
      if (!singleImageView()) {
        playbackKeys = [32];      // Space (32)
        if ($.inArray(event.keyCode, playbackKeys) >= 0) return playback();

        nextKeys = [39, 78];      // Right arrow (39), 'n' (78)
        if ($.inArray(event.keyCode, nextKeys) >= 0) return showNextImage();

        prevKeys = [37, 80];      // Left arrow (37), 'p' (80)
        if ($.inArray(event.keyCode, prevKeys) >= 0) return showPrevImage();
      }

  		closeKeys = [27, 88, 67]; // Esc (27), 'x' (88), 'c' (67)
      if ($.inArray(event.keyCode, closeKeys) >= 0) return closePlayer();
    });
  } // setupKeyEvents

  function showPrevImage() {
    if (prevImageIndex != null) {
      currentlyPlaying = false;
      $(containerElement).stopTime("lbn");
      $(playbackButtonElement).css("background-position", "0px 0px");
      return changeImage(prevImageIndex);
    } else return false;
  } // showPrevImage

  function showNextImage() {
    if (nextImageIndex != null) {
      currentlyPlaying = false;
      $(containerElement).stopTime("lbn");
      $(playbackButtonElement).css("background-position", "0px 0px");
      return changeImage(nextImageIndex);
    } else return false;
  } // showNextImage

  function changeImage(newIndex) {
    $("#niftyPlayer").css("visibility", "hidden");
    currentImageIndex = newIndex;
    prevImageIndex = currentImageIndex - 1 >= 0 ? currentImageIndex - 1 : null;
    nextImageIndex = currentImageIndex + 1 < images.length ? currentImageIndex + 1 : null;

    if (!singleImageView()) moveSlider(currentImageIndex);

    preload = new Image();
    $(preload).bind("load", null, function() {
      $(captionElement).html(images[currentImageIndex][2]).hide();

      maxWidth = $(imageElement).innerWidth() - 10;   // -10px to account for the 5px border
      maxHeight = $(imageElement).innerHeight() - 10; // -10px to account for the 5px border
      if (images[currentImageIndex][2]) maxHeight -= $(captionElement).outerHeight();

      optWidth = preload.width;
      optHeight = preload.height;

      if (optWidth > maxWidth || optHeight > maxHeight) {
        aspectRatio = preload.width / preload.height;
        optWidth = maxWidth / aspectRatio > maxHeight ? maxHeight * aspectRatio : maxWidth;
        optHeight = maxWidth / aspectRatio > maxHeight ? maxHeight : maxWidth / aspectRatio;
      }

      $("img", $(imageElement)).remove();
      $(imageElement).prepend(
        $('<img/>').attr("src", preload.src).css({
          width: optWidth,
          height: optHeight,
          left: Math.round((maxWidth - optWidth) / 2),
          top: Math.round((maxHeight - optHeight) / 2)
        })
      );

      if (images[currentImageIndex][2]) {
        $(captionElement).css({
          width: optWidth - 20,
          left: Math.round((maxWidth - optWidth) / 2),
          top: Math.round((maxHeight - optHeight) / 2) + optHeight + 10
        }).show();
      }
    });
    preload.src = images[currentImageIndex][0];

    if (prevImageIndex != null) preloadPrev.src = images[prevImageIndex][0];
    if (nextImageIndex != null) preloadNext.src = images[nextImageIndex][0];

    return false;
  } // changeImage

  function playback() {
    if (currentlyPlaying == true) {
      currentlyPlaying = false;
      $(containerElement).stopTime("lbn");
      $(playbackButtonElement).css("background-position", "0px 0px");
    } else if (currentlyPlaying == false && nextImageIndex != null) {
      currentlyPlaying = true;
      $(playbackButtonElement).css("background-position", "-70px 0px");
      $(containerElement).everyTime(1500, "lbn", function() {
        if (nextImageIndex != null) {
          changeImage(nextImageIndex);
        } else {
          $(containerElement).stopTime("lbn");
          $(playbackButtonElement).css("background-position", "0px 0px");
        }
      }, 0, true);
    }

    return false;
  } // playback

  function closePlayer() {
    $(containerElement).fadeOut(300, function() {
      $(overlayElement).fadeOut(300, function() {
        clearSlider();
        $(playbackButtonElement).css("background-position", "0px 0px");
        $("img", $(imageElement)).remove();
        $("#niftyPlayer").css("visibility", "visible");
      });
    });

    currentlyPlaying = false;
    $(containerElement).stopTime("lbn");

    return false;
  } // closePlayer

  /**
   *  Helper. Returns true if there's only a single image to be displayed.
   *  This implies, that the image slider/selection isn't required.
   */
  function singleImageView() {
    return images.length == 1;
  } // singleImageView
})(jQuery);

