/**
 * Slideshow used in Sanctuary's web site. Every page has a slideshow. However,
 * their gallery page has a special implementation of this slideshow that features
 * a thumbnail slider view at the bottom of the current slide. It currently displays
 * inside a shadowbox, and shows over 70 images.
 */

/**
 * SlideshowSlide - simple container object for holding slide data
 * PUBLIC MEMBERS:
 * url - string image url
 * caption - string image caption
 * title - string image title
 * loading - true when image is loading
 * Constructor:
 * @param url string url to slide image
 * @param caption string image caption to show in navigation bar at bottom
 * @param title string image title
 */
SlideshowSlide = function(url, caption, title) {
   this.url = url;
   this.caption = caption;
   this.title = title;
   this.loading = false;
};

/**
 * Slideshow - create a slideshow with a given container element
 * Example implementation (requires jQuery):
 * <code>
 *    $(function() {
 *       var slideshow = new Slideshow($("#img-module"));   
 *       slideshow.addSlide("/path/to/image.png", "Hey there!", "sub caption goes here");
 *       slideshow.addSlide("/path/to/image1.png", "Hey there 1!", "sub caption goes here");
 *       slideshow.addSlide("/path/to/image2.png", "Hey there 2!", "sub caption goes here");
 *       slideshow.addSlide("/path/to/image3.png", "Hey there 3!", "sub caption goes here");
 *       slideshow.render();
 *    });             
 * </code>
 * @param domEl - DIV element on page that will contain the slideshow.
 */
Slideshow = function(domEl) {
   var self = this;   
   this.slides = new Array();
   var jqElement = $(domEl);
   var jqThumbnailStrip = null;
   var iThumbnailStripLength = 8;
   this.iThumbnailWidth = 142;
   this.iCurrentSlide = 0;
   var iPrevSlide = null;
   var iSlideDelay = 3000; // milliseconds
   var iFadeDuration = 2500; // milliseconds 2500 Original
   var bSoftPause=false;
   var bActivateThumbMover = false;
   var iThumbnailMoveStep = 0;
   self.timer = null;
   this.thumbs = null;
   var bHardPause = false;
   var bThumbStripHoverState = false;

   this.hardPause = function() {
      bHardPause = true;
      jqElement.addClass("paused");
   }

   this.hardResume = function() {
      bHardPause = false;
      jqElement.removeClass("paused");
   }

   this.getLastSlideNum = function() {
      return self.slides.length - 1;
   };

   this.getPreviousSlideNumber = function() {
      return (self.iCurrentSlide == 0) ? self.getLastSlideNum():self.iCurrentSlide-1;      
   }
   
   this.decrementSlide = function() {
      self.iCurrentSlide = self.getPreviousSlideNumber();
   };

   this.getNextSlideNumber = function() {
      iPrevSlide = parseInt(self.iCurrentSlide);
      return (self.iCurrentSlide == self.getLastSlideNum()) ? 0:self.iCurrentSlide + 1;      
   }
   
   this.incrementSlide = function() {
      self.iCurrentSlide = self.getNextSlideNumber();
   };

   this.selectSlide = function(iSlideId) {
      iPrevSlide = parseInt(self.iCurrentSlide);
      self.iCurrentSlide = iSlideId;
   }
   
   this.softPause = function() {
      bSoftPause = true;
   };
   
   this.softResume = function() {
      bSoftPause = false;
   };
   
   /**
    * Sets the global timer for the slide show.
    */
   this.play = function() {
      if(self.timer !== null) {
         window.clearInterval(self.timer);
      }
      self.timer = window.setInterval(function() { 
         if(!bSoftPause && !bHardPause && self.nextSlideLoaded()) {
            self.incrementSlide();
            self.showSlide();
         }
      }, iSlideDelay + iFadeDuration);      
   };
   
   this.showSlide = function(bImmediate) {
      if (bImmediate == undefined) { bImmediate = false; }
      if (self.iCurrentSlide == iPrevSlide) return false;
      
      if (bImmediate === true) { jQuery.fx.off = true; }
      if (jQuery.browser.msie) {
         $("#slideimage-"+self.iCurrentSlide + " .slideshow-caption").show();
         var currentEl = jqElement.find("#slideimage-"+self.iCurrentSlide).stop(true,true).fadeIn(iFadeDuration, function() { $(this).show(); });
         $("#slideimage-"+iPrevSlide + " .slideshow-caption").hide();
         jqElement.find("#slideimage-"+iPrevSlide).stop(true,true).fadeOut(iFadeDuration, function() { jqElement.find(".slideimage").not(currentEl).hide(); });
      } else {
         var currentEl = jqElement.find("#slideimage-"+self.iCurrentSlide).stop(true,true).fadeIn(iFadeDuration,function() {$(this).show();});
         jqElement.find("#slideimage-"+iPrevSlide).stop(true,true).fadeOut(iFadeDuration, function() { jqElement.find(".slideimage").not(currentEl).hide(); });
      }        
      if (bImmediate === true) { jQuery.fx.off = false; }
      
      if(jqThumbnailStrip) {
         self.selectThumbnail(self.iCurrentSlide,bImmediate);
      }
      
   };

   this.addSlide = function(url, caption, title) {
      self.slides[self.slides.length] = new SlideshowSlide(url, caption, title);
   };
   
   this.selectThumbnail = function(iSlide,bImmediate) {
      if (iSlide === undefined) { iSlide = self.iCurrentSlide; }      
      var currentThumb = jqThumbnailStrip.find(".thumbnail-" + iSlide);
      var otherThumb = jqThumbnailStrip.find(".thumbnail").not(currentThumb);                        
      otherThumb.removeClass("showing");
      currentThumb.addClass("showing");
      self.positionStripToCurrentThumb(iSlide,currentThumb,bImmediate);
   };

   this.isThumbVisible = function(iSlide) {
      var iSlideWidth = 120;
      var iNumSlidesToSkip = 7;
      var iSevenSlides = iSlideWidth * 7;
      var iCurrentStripPos = jqThumbnailStrip.position().left;
      var iCurrentSlidePos = iSlideWidth * (iSlide);
      var bCheck1 = (iCurrentStripPos <= (iCurrentSlidePos * -1));
      var bCheck2 = (iCurrentStripPos > ((iCurrentSlidePos - iSevenSlides) * -1));
      var bVisible = !bCheck1 && !bCheck2;
      return bVisible;
   }

   this.positionStripToCurrentThumb = function(iSlide,thumb,bImmediate) {
      var iSlideWidth = 120;
      var iNumSlidesToSkip = 4;
      var iSevenSlides = iSlideWidth * 5;
      var iEndPos = iSlideWidth * (self.slides.length - 8) * -1;
      var iCurrentStripPos = jqThumbnailStrip.position().left;
      var iCurrentThumbPos = thumb.position().left;
      if(iSlide > (iNumSlidesToSkip - 1) && iSlide < (self.slides.length - 3)) {
         if(bThumbStripHoverState) { // don't re-position the thumbs if the mouse is already on the thumbnail strip.
            iCurrentThumbPos = iCurrentStripPos;
         } else {
            iCurrentThumbPos = (((iSlideWidth * (iSlide+1)) - iSevenSlides) * -1);
         }
      } else {
         if(iSlide > (iNumSlidesToSkip - 1)) {
            iCurrentThumbPos = iEndPos;
         } else {
            iCurrentThumbPos = 0;
         }
      }
      if (bImmediate === true) { jQuery.fx.off = true; }
      jqThumbnailStrip.stop(true,true).animate({"left":iCurrentThumbPos},{"duration":1000,complete:self.loadVisibleThumbs});
      if (bImmediate === true) { jQuery.fx.off = false; }
   }
   
   /**
    * @param domElement or JQEl in which to place the strip
    * @param config { fnThumbnailUrl(slide) }
    */
   this.addThumbnailStrip = function(element, config) {
      if (config !== undefined) {
         if (config.fnThumbnailUrl !== undefined) {
            self.fnThumbnailUrl = config.fnThumbnailUrl; 
         }
      }
      jqEl = $(element);
      jqEl.append("<div class='thumbnail-strip-container'></div>");
      jqThumbnailStrip = jqEl.find(".thumbnail-strip-container");
      jqThumbnailStrip.hover(function() {
         bActivateThumbMover = true;
         bThumbStripHoverState = true;
      },function() {
         bActivateThumbMover = false;
         bThumbStripHoverState = false;
      });
      
      for (var counter=0; counter < self.slides.length; counter++) {
         var fn = function(iSlide) {
            var runnable = function() {
               var thumbnail = "<span class='thumbnail-holder'><img style='display:none;' class='thumbnail thumbnail-" + iSlide + "' src='' loadurl='"+self.fnThumbnailUrl(self.slides[iSlide])+"' loaded='false' sequence='"+iSlide+"' /></span>";
               jqThumbnailStrip.append(thumbnail);
               $(".thumbnail-" + iSlide).click(function() {
                  self.hardPause();
                  self.selectSlide(iSlide);
                  self.showSlide(true);
               });
            };
            runnable();
         };
         fn(counter);
      }

      jqThumbnailStrip.mwheelIntent(function(event,delta) {
         var iStep = parseInt(event.originalEvent.wheelDeltaX);
         self.moveThumbnails(iStep);
         event.preventDefault();
      });

      $('.thumbnail').each(function() {
         $(this).load(function() {
            $(this).css('display','inline-block');
         });
      });

      
   };

   this.showPreviousSlide = function() {
      if(jqThumbnailStrip) {
         var currentThumb = jqThumbnailStrip.find(".thumbnail-" + self.iCurrentSlide);
      }
      self.decrementSlide(); 
      self.showSlide(true);
   }

   this.showNextSlide = function() {
      if(jqThumbnailStrip) {
         var currentThumb = jqThumbnailStrip.find(".thumbnail-" + self.iCurrentSlide);
      }
      self.incrementSlide();
      self.showSlide(true);
   }

   this.onRender = function() {
      // Init
      if(self.slides.length > 1) {
         jqElement.find(".arrow-left").live("click", function() {
            self.showPreviousSlide();
         });

         jqElement.find(".arrow-right").live("click", function() {
            self.showNextSlide();
         });
         
         jqElement.find('.slideshow-caption').hover(self.softPause,self.softResume);         
         self.showSlide(true);
         
      } else {
         window.setTimeout(function() {
               jqElement.find(".arrow-left").addClass('hide');
               jqElement.find(".arrow-middle").addClass('hide');
               jqElement.find(".arrow-right").addClass('hide');
            }, 
            100
         );            
      }

      if(jqThumbnailStrip) {
         self.renderThumbnails();
      }

      var iLoadLength = (jqThumbnailStrip) ? 8:self.slides.length; // XXJON

      // Load only a maximum of 8 slides if they exist.
      for(var i = 0; i < iLoadLength; i ++) {
         if(self.slides.length > i) {
            self.loadSlide(i);
         }
      }

      if(self.slides.length > 1) {
         self.play();
      }

      // activate arrow keys to navigate slides
      $(document).keydown(function(event) {
         switch(event.which) {
            case 39: // right arrow
               self.hardPause();
               self.showNextSlide();
               break;
            case 37: // left arrow
               self.hardPause();
               self.showPreviousSlide();
               break;
         }
      });
   }

   this.thumbnailMover = function() {
      if(bActivateThumbMover) {
         self.moveThumbnails(self.iThumbnailMoveStep);
      }
   }

   this.loadVisibleThumbs = function() {
      if(self.thumbs === null) self.thumbs = $('.thumbnail');
      self.thumbs.each(function() {
         var iSlide = $(this).attr('sequence');
         if(self.isThumbVisible(iSlide) && !self.slides[iSlide].loading) {
            self.slides[iSlide].loading = true;
            self.loadSlide(iSlide);
         }
      });
   }

   this.moveThumbnails = function(iStep) {
      var iCurrentPos = parseInt(jqThumbnailStrip.css('left'));
      var rightBound = (parseInt(jqThumbnailStrip.css("width")) * -1) + 960;
      if(iCurrentPos > 1 || iCurrentPos < rightBound) {
      } else {
         var iNewPos = iCurrentPos + iStep;
         if(iNewPos > 0) iNewPos = 0;
         if(iNewPos < rightBound) iNewPos = rightBound;
         jqThumbnailStrip.css('left',iNewPos);
      }
      self.loadVisibleThumbs();
   }

   this.renderThumbnails = function() {
      iPrevSlide = self.getLastSlideNum();
      self.iCurrentSlide = 0;
      
      jqElement.find(".button-play").live("click", self.hardResume);
      jqElement.find(".button-pause").live("click", self.hardPause);
      
      var jqStrip = jqElement.find(".thumbnail-strip");
      var stripOffset = jqStrip.position();
      var stripWidth = jqStrip.outerWidth(true); 
      
      jqStrip.mousemove(function(e) { 
         var pct = Math.ceil((e.pageX - stripOffset.left) / stripWidth * 100);
         switch(true) {
            case (pct > 0 && pct < 40): //                 Range:     |****      |
               bActivateThumbMover = true;
               self.iThumbnailMoveStep = (43 - pct);
               break;
            case (pct > 40 && pct < 60): //                           |    **    |
               bActivateThumbMover = false;
               break;
            case (pct > 60 && pct < 100): //                          |      ****|
               bActivateThumbMover = true;
               self.iThumbnailMoveStep = ((pct - 57)* -1);
               break;
         }

         if(!self.thumbtimer) {
            self.thumbtimer = window.setInterval(self.thumbnailMover,50);
         }
      });


      jqStrip.find(".thumbnail").live("mouseenter", 
            function() { 
               $(this).addClass("bright");
            }
      );
      jqStrip.find(".thumbnail").live("mouseleave", 
            function() { 
               $(this).removeClass("bright");
            }
      );
      
      jqStrip.hover(
            function() {
               self.softPause();                  
            },
            function() {
               self.softResume();
            }
      );
   };

   this.loadSlide = function(iSlide) {
      $('.thumbnail-'+iSlide).each(function() {
         $(this).attr('src',$(this).attr('loadurl'));
      });
      $('#largeimage-'+iSlide).each(function() {
         var strLargeLoadUrl = $(this).attr('loadurl');
         $(this).attr('src',strLargeLoadUrl);
         $(this).load(function() {
            $('.images').css('background-image','none');
            $('.thumbnail-'+iSlide).parent().css('background-image','none');
            $(this).parent().attr('loaded','true');
            if(self.slides.length == 1) {
               self.showSlide(0);
            }
         });
      });
   }

   this.slideLoaded = function(iSlide) {
      var bRet = false;
      if($('#slideimage-'+iSlide).attr('loaded') == 'true') {
         bRet = true;
      }
      return bRet;
   }

   this.currentSlideLoaded = function () {
      return self.slideLoaded(self.iCurrentSlide);
   };

   this.nextSlideLoaded = function() {
      return self.slideLoaded(self.getNextSlideNumber());
   }
   
   this.render = function() {
      
      /* Insert Slide Divs */
      for (var iSlide=0; iSlide < this.slides.length; iSlide++) {
         var runnable = function(slidenum) {
            var slide = self.slides[slidenum];
            var tmp   = self;
            var html = "" +
            		"<div id='slideimage-XXSEQUENCEXX' class='slideimage' style='display:none;' width='960' height='450' sequence='XXSEQUENCEXX' loaded='false'>" +
            		"   <img src='' loadurl='XXURLXX' alt='XXTITLEXX' sequence='XXSEQUENCEXX' id='largeimage-XXSEQUENCEXX'>" +
            		"   <div id='slidecaption-XXSEQUENCEXX' class='slideshow-caption'>" +
            		"      <div class='caption-text'>XXCAPTIONXX</div>" +
            		"      <div class='arrow-text'>XXTITLEXX</div>" +
            		"      <div class='arrow-left'></div>" +
            		"      <div class='arrow-middle'></div>" +
            		"      <div class='arrow-right'></div>" +
         		   "   </div>" +
         		   "</div>";
            html = html.replace(/XXSEQUENCEXX/g, "" + slidenum);            
            html = html.replace(/XXURLXX/g, slide.url);
            html = html.replace(/XXTITLEXX/g, slide.title);
            html = html.replace(/XXCAPTIONXX/g, slide.caption);
            jqElement.find(".images").append(html);

         };

         runnable(iSlide);

      }
      
      self.onRender();
   };

};

