/*
Dynamic HTML Slideshow v1.0

Author: James X. Anderson
Created: 2011-08-25

To Do
- setup controllers
- Multiple transition types
- Reduce CPU/memory usage?
  - hopefully css transitions helped with this

Features
- loads slides consecutively after the page loads making page load faster
- CSS3 Transitions with fallback to javascript
- Mouse hover pause: on mouse out resume if not not previously paused
*/

(function ($) {
  // jQuery.support.transition
  // Author: - https://gist.github.com/373874
  // to verify that CSS3 transition is supported (or any of its browser-specific implementations)
  $.support.transition = (function(){ 
    var thisBody = document.body || document.documentElement,
    thisStyle = thisBody.style,
    support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined;

    return support; 
  })();

  jQuery.fn.dynamicSlideshow = function(options, slides) {

    options = options || {};
    options.duration = options.duration || 5000;
    options.filePath = options.filePath || './slides/';
    options.slideIdPrefix = options.slideIdPrefix || 'dynamicSlide_';
    options.slideClass = options.slideClass || 'slide';
    options.currentClass = options.currentClass || 'current'; // what class to apply to current slide and current controller
    options.transitionDuration = options.transitionDuration || 1000;
    options.cssTransitions = options.cssTransitions || false;
    /* default controller style is thumbnails */
    options.controllerStyle = options.controllerStyle || 'number';
    options.hoverPause = options.hoverPause || true;


    var slidesContainer = $(this);
    slides = slides || [];
    var pause = (slides.length == 1) ? 1 : 0;

    var new_index = 0;
    var curr_index = 0;
    var timer = '';
    var waiting_timer = '';
    
    function transitionSlide(slideType, number){
      var new_slide;
      var curr_slide = $(slidesContainer).find('.'+options.currentClass);
      
      switch (slideType){
        case 'firstLoad':
          new_slide = $(slidesContainer).find('.'+options.slideClass).filter(':first');
          break;
        case 'number':
          new_slide = $(slidesContainer).find('#'+options.slideIdPrefix+number);
          break;
        case 'prev':
          if ($(curr_slide).is($(slidesContainer).find('.'+options.slideClass).filter(':first'))){
            new_slide = $(slidesContainer).find('.'+options.slideClass).filter(':last');
          }
          else {
            new_slide = $(curr_slide).prev('.'+options.slideClass);
          }
          break;
        case 'next':
        default:
          if ($(curr_slide).is($(slidesContainer).find('.'+options.slideClass).filter(':last'))){
            new_slide = $(slidesContainer).find('.'+options.slideClass).filter(':first');
          }
          else {
            new_slide = $(curr_slide).next('.'+options.slideClass);
          }
          
          break;
      }
      
      if (options.cssTransitions && $.support.transition) {
      // no animation to do here thanks to CSS3
      }
      else {
        // begin new slide fade in
        $(new_slide).animate({
          opacity: 1
        }, options.transitionDuration);
        
        // begin current slide fade in
        $(curr_slide).animate({
          opacity: 0
        }, options.transitionDuration);
      }
      
      $(new_slide).addClass(options.currentClass);
      $(curr_slide).removeClass(options.currentClass);

      // update controller to active
      if (options.controllerActiveClass) {
        $('.'+options.controllerClass).removeClass(options.controllerActiveClass);
        $('#'+options.controllerIdPrefix + new_index).addClass(options.controllerActiveClass);
      }
     
      if (pause == 1) {
        // pause the show
        // display correct image
        clearTimeout(timer);
      }
      else {
        // continue slideshow
        // mark image as loaded so it doesn't trigger .load() again
        slides[new_index].loaded = true;
            
        if (new_index >= slides.length - 1) {
          new_index = 0;
        }
        else {
          new_index++;
        }

        if (curr_index >= slides.length - 1 || (curr_index + 1) == new_index) {
          curr_index = 0;
        }
        else {
          curr_index++;
        }

        timer = setTimeout(function (){
          initSlider()
        } , options.duration );
      }
    }

    function initSlider() {
      if (slides[new_index].loaded) {
        transitionSlide('next');
      }
      else {
        waiting_timer = setTimeout(function(){
          waitingForSlideLoad('next', new_index)
        }, 500);
      }
    }
    
    function loadSlides(slide_index){
      slide_index = slide_index || 0;
      
      // generate random seed so that browsers don't cache ajaxed file
      var preventCache = '?ms=' + new Date().getTime();
      
      // load a new image into the foreground
      $.get(options.filePath + slides[slide_index].fileName + preventCache, function(data){
        if (data != '') {
          $(slidesContainer).append(data);
          // apply id to slide
          $(slidesContainer).find('.'+options.slideClass).filter(':last').attr('id',options.slideIdPrefix+slide_index);
          // load the first slide once all slides have loaded
          // provides a small amount of delay so that images in first slide can load fully
          if ((slide_index + 1) === slides.length){
            clearWaitingForSlideLoad();
            transitionSlide('firstLoad');
          }
          slides[slide_index].loaded = true;
          var new_index = slide_index + 1;
          
          if (new_index < slides.length) {
            loadSlides(new_index);
          }
        }
      });
    }
    
    function waitingForSlideLoad(slideType, slide_index) {
      $(slidesContainer).css('cursor', 'progress');
      
      if (slides[slide_index].loaded) {
        $(slidesContainer).css('cursor', 'auto');
        clearTimeout(waiting_timer);
        transitionSlide(slideType, slide_index);
      }
      else {
        waiting_timer = setTimeout(function(){
          waitingForSlideLoad(slideType, slide_index)
        }, 500);
      }
    }
    
    function clearWaitingForSlideLoad() {
      $(slidesContainer).css('cursor', 'auto');
      clearTimeout(waiting_timer);
    }
    
    
    // setup controllers
    if (options.controllerClass != '' && options.controllerIdPrefix != ''){
    /*
      // fill the controller box with thumbnails
      if (options.controllerContainer != '' && options.autoControllers) {
        $('#' + options.controllerContainer).empty();
        if (options.controllerStyle == 'thumb') {
          jQuery.each(slides, function(index, imgObj){
            var thumb_prefix = imgObj.imgName.substring(0, imgObj.imgName.lastIndexOf("."));
            var thumb_ext = imgObj.imgName.substring(imgObj.imgName.lastIndexOf(".") + 1);
            $('#' + options.controllerContainer).append('<img id="'+ options.controllerIdPrefix + index +'" class="'+ options.controllerClass +'" src="'+ options.imgPath + thumb_prefix + options.controllerThumbSuffix +'.'+ thumb_ext +'"/>');
          });
        }
        else if (options.controllerStyle == 'number') {
          jQuery.each(slides, function(index){
            if (index != 0 && options.controllerSpacer && options.controllerSpacerClass){
              // add the spacer
              $('#' + options.controllerContainer).append('<span class="'+ options.controllerSpacerClass +'">'+ options.controllerSpacer +'</span>');
            }
            $('#' + options.controllerContainer).append('<span id="'+ options.controllerIdPrefix + index +'" class="'+ options.controllerClass +'">'+ (index+1) +'</span>');
          });
        }
        else if (options.controllerStyle == 'empty') {
          jQuery.each(slides, function(index){
            if (index != 0 && options.controllerSpacer && options.controllerSpacerClass){
              // add the spacer
              $('#' + options.controllerContainer).append('<span class="'+ options.controllerSpacerClass +'">'+ options.controllerSpacer +'</span>');
            }
            $('#' + options.controllerContainer).append('<span id="'+ options.controllerIdPrefix + index +'" class="'+ options.controllerClass +'"></span>');
          });
        }
      }

      // manage clicking on controllerContainer items
      $('.' + options.controllerClass).click(function(e){
        e.preventDefault();

        clearTimeout(timer);

        var tempCurr = $(this).attr('id').replace(options.controllerIdPrefix, '');

        if (tempCurr == 'pause') {
          $(this).attr('id', options.controllerIdPrefix + 'play');
          pause = 1;
          if (new_index == 0) {
            new_index = slides.length - 1;
          }
          else {
            new_index = new_index - 1;
          }
        }
        else if (tempCurr == 'play') {
          $(this).attr('id', options.controllerIdPrefix + 'pause');
          pause = 0;
          // continue slideshow
          curr_index = new_index;

          if (new_index >= slides.length - 1) {
            new_index = 0;
          }
          else {
            new_index++;
          }

          initSlider(slidesContainer, slides);
        }
        else {
          if (pause == 0) {
            if (new_index > 0) {
              curr_index = new_index - 1;
            }
            else {
              curr_index = slides.length - 1;
            }
          }
          else {
            curr_index = new_index;
          }

          $('#'+options.controllerIdPrefix + 'pause').attr('id', options.controllerIdPrefix + 'play');

          if ((tempCurr != new_index && pause == 1) || (pause == 0)) {
            pause = 1;
            new_index = tempCurr;
            $(slidesContainer).find('img:first').animate({
              opacity: 0.0
            }, options.transitionDuration, function() {
              $(this).remove();
            });
            initSlider(slidesContainer, slides);
          }
        }
      });
      
      */

    }
    
    if (options.controllerPadClass != ''){
      // manage clicking on left and right pads
      $('.' + options.controllerPadClass).click(function(e){
        e.preventDefault();

        clearTimeout(timer);

        var temp_pad = 'right';
        var temp_direction = 'next';
        
        if ($(this).attr('class').match(/left/i)) {
          temp_pad = 'left';
          temp_direction = 'prev';
        }
        
        pause = 1;
        $('#'+options.controllerIdPrefix + 'pause').attr('id', options.controllerIdPrefix + 'play');
        
        // get the index of the slide with class "current"
        curr_index = Number($(slidesContainer).find('.'+options.currentClass).attr('id').replace(options.slideIdPrefix, ''));
        new_index = (temp_pad == 'right') ? curr_index + 1 : curr_index - 1;

        if (new_index > (slides.length - 1)) {
          new_index = 0;
        }
        else if (new_index < 0) {
          new_index = slides.length - 1;
        }
        
        if (slides[new_index].loaded) {
          transitionSlide(temp_direction);
        }
        else {
          waiting_timer = setTimeout(function(){
            waitingForSlideLoad('number', new_index)
          }, 500);
        }
      });
    }
    
    if (options.hoverPause) {
      var pausedBeforeHover = false;
      $(slidesContainer).hover(function(){
        if (pause == 1) {
          pausedBeforeHover = true;
        }
        clearTimeout(timer);
        pause = 1;
      },
      function(){
        if (pausedBeforeHover) {
        // do nothing
        }
        else {
          // resume slideshow
          pause = 0;
          timer = setTimeout(function (){
            initSlider()
          } , options.duration );
        }
      });
    }
    
    loadSlides();
  }
})(jQuery);
