function Slideshow(numImages, slideshowId, timer, useCaptions, videoId)
{
  if (videoId) {
  	$('.slideshow').css('margin-top', '26px');
    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/player_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    window.onYouTubePlayerAPIReady = function() {
      var player = new YT.Player('slideshow_'+slideshowId, {
        height: '383',
        width: '960',
        videoId: videoId,
        playerVars: { 'autoplay': 1, 'controls': 0 },
        events: {
          'onReady': function(event) {
            event.target.playVideo();
          }
        }
      });
    }
    
    return;
  }
  
  this.numImages = numImages;
  this.slideshowId = slideshowId;
  this.timer = timer;
  this.timeout = null;
  this.curr = 0;
  this.prev = numImages - 1;
  this.next = 1;
  this.timeout = null;
  this.fade = 1000;
  this.busy = false;
  this.width = 656;
  this.captionHeight = 50;
  this.paused = false;
  selfRef = this;
  this.images = new Array();
  this.captions = new Array();
  
  if (typeof(useCaptions) == 'undefined') {
    useCaptions = true;
  }
  
  $('#slideshow_' + this.slideshowId).addClass('active');
  $('#slideshowCounter_' + this.slideshowId).append('<div class="floatWrapper" id="floatWrapper_' + this.slideshowId + '"></div>');
  floatWrapper = $('#floatWrapper_' + this.slideshowId);
  
  var boxes = "";
  
  for (i = 0; i < numImages; i++)
  {
    
    this.images[i] = document.getElementById('slide_' + slideshowId + '_' + i);
    if (useCaptions) {
      this.captions[i] = document.getElementById('caption_' + slideshowId + '_' + i);
    }
    
    if (i == this.curr)
    {
      boxes = boxes + '<div id="goTo_slide_' + this.slideshowId + '_' + i + '" class="goTo current"></div>';
    }
    else
    {
      boxes = boxes + '<div id="goTo_slide_' + this.slideshowId + '_' + i + '" class="goTo"></div>';
    }
  }
  
  boxes = boxes + '<div class="slideshowCounterPrev" id="slideshowCounter_' + this.slideshowId + '_Prev"></div>';
  boxes = '<div class="slideshowCounterNext" id="slideshowCounter_' + this.slideshowId + '_Next"></div>' + boxes;
  $(floatWrapper).append(boxes);
  
  this.prevArrow = $('#slideshowCounter_' + this.slideshowId + '_Prev');
  this.nextArrow = $('#slideshowCounter_' + this.slideshowId + '_Next');
  $(this.prevArrow).animate({ opacity: 0 }, 0);
  $(this.nextArrow).animate({ opacity: 0 }, 0);

  $(this.images[this.curr]).css('zIndex', '2');
  $(this.images[this.next]).hide();
  $(this.images[this.next]).css('zIndex', '3');
  
  this.timeout = setTimeout( function() { selfRef.forward(true) }, this.timer);
  
  // Event handlers     
  $('.goTo').live('click', function()
  {
    ssId = (($(this).attr('id')).split('_'))[2];
    if (ssId == selfRef.slideshowId)
    {         
      id = (($(this).attr('id')).split('_'))[3];
      selfRef.goTo(id);
    }
  })
  
  $('#slideshowCounter_' + this.slideshowId + '_Prev').click(function()
  {
    selfRef.back();
  })
  
  $('#slideshowCounter_' + this.slideshowId + '_Next').click(function()
  {
    selfRef.forward();
  })
  
  $('.slideshow').mouseenter(function()
  {
    selfRef.pause();
    $(selfRef.prevArrow).animate({ opacity: 1 }, 500);
    $(selfRef.nextArrow).animate({ opacity: 1 }, 500);
  })
  
  $('.slideshow').mousemove(function()
  {
    if (!selfRef.paused)
    {
      selfRef.pause();
      $(selfRef.prevArrow).animate({ opacity: 1 }, 500);
      $(selfRef.nextArrow).animate({ opacity: 1 }, 500);
    }
  })
  
  $('.slideshow').mouseleave(function()
  {
    selfRef.unPause();
    $(selfRef.prevArrow).animate({ opacity: 0 }, 500);
    $(selfRef.nextArrow).animate({ opacity: 0 }, 500);
  })
}

Slideshow.prototype.pause = function()
{
  if (!this.paused)
  {
    clearTimeout(this.timeout);
    this.paused = true;
  }
}

Slideshow.prototype.unPause = function()
{
  if (this.paused)
  {
    clearTimeout(this.timeout);
    this.timeout = setTimeout(function() { selfRef.forward(true); }, this.timer);
    this.paused = false;
  }  
}

Slideshow.prototype.forward = function(auto)
{
  this.goTo(this.next, auto);
}

Slideshow.prototype.back = function()
{
  this.goTo(this.prev, false);
}

Slideshow.prototype.goTo = function(slideId, auto)
{
  if (!this.busy && this.next != this.curr)
  {
    clearTimeout(this.timeout);
    this.next = slideId;
    this.showNext(auto);
  }
}

Slideshow.prototype.showNext = function(auto)
{
  if (!this.busy)
  {
    selfRef = this;
    this.busy = true;
    
    // Hide the next image, and put it on the top, then fadeIn
    $(this.images[this.next]).hide();
    $(this.images[this.next]).css('zIndex', '3');
    $(this.images[this.curr]).css('zIndex', '2');
    if (this.prev != this.next)
    {
      $(this.images[this.prev]).css('zIndex', '1');
    }
    
    // Update the counter boxes to reflect any changes
    $('#goTo_slide_' + this.slideshowId + '_' + this.curr).removeClass('goTo current').addClass('goTo');
    $('#goTo_slide_' + this.slideshowId + '_' + this.next).addClass('goTo current');
    $(this.images[this.next]).fadeIn(this.fade, function()
    {
      // Hide the old one when we're done, and put the current one in the middle of the zindex stack
      $(selfRef.images[selfRef.curr]).css('zIndex', '1');
      $(selfRef.images[selfRef.next]).css('zIndex', '2');
      
      // Reset the indexes to point at the new images. Always assume that next is the variable with correct value. Set the others accordingly.
      selfRef.curr = selfRef.next;
      selfRef.next++;
      selfRef.prev = selfRef.curr - 1;
                
      if (selfRef.next >= selfRef.numImages)
      {
        selfRef.next = 0;
      }
      
      if (selfRef.prev < 0)
      {
        selfRef.prev = selfRef.numImages - 1;
      }
      
      // If captions aren't used, trigger next slide here instead.
      if (!selfRef.captions.length) {
        selfRef.busy = false;
        if (auto && !selfRef.paused)
        {
          selfRef.timeout = setTimeout(function() { selfRef.forward(true); }, selfRef.timer);
        }
      }
    });
    
    // Prepare next caption, if any. Slide out old caption, slide in new caption.
    if (this.captions.length) {
      $(this.captions[this.next]).css('bottom', 0);
      $(this.captions[this.next]).css('opacity', 0);
      
      var nextCaption = this.captions[this.next];
      var captionFade = this.fade/2;
      
      $(this.captions[this.curr]).animate( { opacity:0 }, captionFade, function() {
        $(nextCaption).animate( { opacity:0.5 }, captionFade, function() {
          // When the new caption is in, we're not busy anymore, and we can start the timeout for the next slide if we're on autoslide
          selfRef.busy = false;
          if (auto && !selfRef.paused)
          {
            selfRef.timeout = setTimeout(function() { selfRef.forward(true); }, selfRef.timer);
          }
        });
      });
    }
  }
}
