/*
 * @name LEAP Carousel
 * @desc A carousel with preview for jQuery
 *
 * @author LEAP
 * @version 0.1.0
 * @type jQuery
 * @cat Plugins/leapcarousel
 * @requires jQuery v1.2+ (not tested on versions prior to 1.2.6)
 *
 * No guarantees, warranties, or promises of any kind
 *
 */

;(function($) {

  // Version
  $.leapcarousel = {version: '0.1.0'};

  // Defaults
  $.leapcarousel.defaults = {
 
    // Loading
    loadingCSS:         "lc_loading",  

    // Selectors
    slide: {
      selector:         ".slide",
      animateIn:        function(){ $(this).fadeTo("fast",1); }
    },
    
    // Overlay/caption
    overlay: {
      selector:         ".overlay",      
      init:             function(){ $(this).fadeTo(0,0); },   
      animateIn:        function(){ $(this).fadeTo("slow",1); },
      animateOut:       function(){ $(this).fadeTo("fast",0); }
    },
    
    // Siblings
    siblings: {
      init:             function(){ $(this).fadeTo(0,.6); }, 
      animateOut:       function(){ $(this).fadeTo("fast",.6); }            
    },         

    // Buttons
    buttons: {
      previousCSS:      "lc_previous",
      nextCSS:          "lc_next",       
      init:             function(){ $(this).fadeTo("fast",0); },   
      animateIn:        function(){ $(this).fadeTo("slow",.4); },
      animateOut:       function(){ $(this).fadeTo("fast",0); }    
    },
    
    // Animation
    advance: {
      speed:            'slow',
      easing:           '' //easeOutBack
    },
    autoAdvance: {
      enabled:          true,
      pause:            6,
      pauseAttribute:   'delay',
      speed:            2000,      
      easing:           ''
    }    
    
  }; // defaults
 
  // Constructor 
  $.fn.leapcarousel = function(options){
  
    // Merge options into defaults      
    var opts = $.extend({}, $.leapcarousel.defaults, options);
    
    // Get references
    var lcc=this;
    var height=lcc.height();
    var slide_info=[];
    var center=Math.round(lcc.width()/2);
    var pw=0;
    var current=0;
    var last=null;
    var advancing=opts.autoAdvance.enabled;
    var adv_timeout=null;
        
    // Add architecture
    lcc.css({position:'relative',overflow:'hidden'});      
    var lcl=$('<div class="'+opts.loadingCSS+'" />').appendTo(lcc);
    var slides=$(opts.slide.selector,lcc)
      .css({float:'left',visibility:'visible'})   
      .wrapAll('<div class="lc-panel" ' + 
        'style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;visibility:visible">' + 
        '<div class="lc-set-main" style="float:left;" /></div>')
      .wrapInner('<div class="lc-slide-inner" style="position:relative;top:0;left:0;width:100%;height:100%" />');
    var slide_ct=slides.length;    
    var lcp=$('.lc-panel',lcc)
      .prepend('<div class="lc-set-clone" style="float:left" />')
      .append('<div class="lc-set-clone" style="float:left" />');
    $(opts.overlay.selector,lcc).css({visibility:'hidden'});      
    slides.clone().appendTo($('.lc-set-clone',lcp));
    var lcprev = $('<div class="lc-button ' + opts.buttons.previousCSS + 
      '" style="position:absolute;z-index:10" />').appendTo(lcp);
    var lcnext = $('<div class="lc-button ' + opts.buttons.nextCSS + 
      '" style="position:absolute;z-index:10" />').appendTo(lcp);   
    var lcbuttons = $('.lc-button',lcp).hover(
      function(){ $(this).css({cursor:'pointer'}); },
      function(){ $(this).css({cursor:'auto'}); })
      .each(opts.buttons.init);
    var allslides = $(opts.slide.selector,lcp);
                 
    // Initialize on load
    $(window).load(function(){lcc.setup()});
    
    // When all is loaded
    this.setup = function(){

      // Inventory and position slides
      slides.each(function(){
        pw+=$(this).outerWidth();
      });
      lcp.width(pw*3);      
      slides.each(function(){      
        var s=$(this);
        var w=s.outerWidth();
        var l=parseInt(s.position().left);
        var p=opts.autoAdvance.pause;
        if(opts.autoAdvance.pauseAttribute!=''){
          var pd=parseInt(s.attr(opts.autoAdvance.pauseAttribute));
          if (!isNaN(pd) && pd>0) p=pd;
        }
        var i=s.find("img");
        i.each(opts.siblings.init);
        slide_info[slide_info.length]={
          s: s,
          i: i,
          o: s.find(opts.overlay.selector)
            .css({visibility:'visible'})
            .each(opts.overlay.init),
          p: p*1000,
          w: w,
          c: Math.round(w/2,0),
          l: l,
          r: l+w
        };
      });
            
      // Position items
      lcc.reposition('');     
      
      // Reveal carousel
      lcl.fadeOut("slow",function(){
      
        // Set up hover on carousel
        if(advancing)lcc.hoverIntent({
          over: function(){
            clearTimeout(adv_timeout);
            advancing=false;
          },
          out: function(){
            advancing=true;
            lcc.autoAdvance();
          }
        });         
      });
    };
    
    this.reposition = function(dir){
      // Clear timeout
      clearTimeout(adv_timeout);
      
      // Get advancing options
      var advance=opts.advance;
      if (advancing) advance=opts.autoAdvance;
      var sp=advance.speed;

      // Get properties
      var li=(last!=null)?slide_info[last]:null;
      var ci=slide_info[current];

      // Unwire all slides
      allslides.unbind('click mouseenter mouseleave');
      
      // Hide buttons
      lcbuttons.each(opts.buttons.animateOut);      

      // If first time, set position
      if (li==null){
        sp=0;   
        
      // Reset last item           
      } else {     
        li.o.each(opts.overlay.animateOut);
        li.i.each(opts.siblings.animateOut);        
        
        // Switch to clone if needed
        var lastli=parseInt(lcp.css("left"));
        if (last==0 && current==slide_ct-1)
          lcp.css("left",(lastli-pw)+'px');
        if (last==slide_ct-1 && current==0)
          lcp.css("left",(lastli+pw)+'px');
      } 
      
      // Adjust panel
      lcp.animate({left:(center-ci.l-ci.c)+'px'},
        sp,advance.easing,function(){
        
        // Show current item and overlay
        ci.i.each(opts.slide.animateIn);
        ci.o.each(opts.overlay.animateIn);        
        
        // Wire adjoining slides
        allslides.eq(current+slide_ct-1).hover(
          function(){
            lcprev=$(this).find(".lc-button")
              .each(opts.buttons.animateIn);
          },
          function(){
            lcprev.each(opts.buttons.animateOut);
          }          
        ).click(function(){lcc.movePrevious('p');})
          .find(".lc-slide-inner")
          .append(lcprev);        
        allslides.eq(current+slide_ct+1).hover(
          function(){
            lcnext=$(this).find(".lc-button")
              .each(opts.buttons.animateIn);
          },
          function(){
            lcnext.each(opts.buttons.animateOut);
          }          
        ).click(function(){lcc.moveNext('n');})
          .find(".lc-slide-inner")
          .append(lcnext);
          
        // Show buttons if clicked
        if (dir=='n') allslides.eq(current+slide_ct+1).trigger('mouseenter')
        else if (dir=='p') allslides.eq(current+slide_ct-1).trigger('mouseenter');                   
        
        // Update last
        last=current;
        
        // Set auto advance
        if (advancing) lcc.autoAdvance();
      });
    }
    
    this.autoAdvance = function(){
      var ci=slide_info[current];
      clearTimeout(adv_timeout);      
      adv_timeout=setTimeout(function(){lcc.moveNext('')},ci.p);
    };  
    
    this.moveNext = function(dir){
      current=(current==slide_ct-1)?0:current+1;
      lcc.reposition(dir);    
    };
    
    this.movePrevious = function(dir){
      current=(current==0)?slide_ct-1:current-1;    
      lcc.reposition(dir);          
    };  
        
  }; // constructor
    
})(jQuery);
