/*
 * jQuery Infinite Carousel
 * @author admin@catchmyfame.com - http://www.catchmyfame.com
 * @version 2.0.2
 * @date June 12, 2010
 * @category jQuery plugin
 * @copyright (c) 2009 admin@catchmyfame.com (www.catchmyfame.com)
 * @license CC Attribution-Share Alike 3.0 - http://creativecommons.org/licenses/by-sa/3.0/
 */

// ECA version

(function($jq){
    $jq.fn.extend({ 
        infiniteCarousel: function(options)
        {
            var defaults = 
            {
                transitionSpeed: 800,
                displayTime: 6000,
                textholderHeight: .25,
                displayProgressBar: true,
                displayThumbnails: true,
                displayThumbnailNumbers: true,
                displayThumbnailBackground: true,
                thumbnailWidth: '20px',
                thumbnailHeight: '20px',
                thumbnailFontSize: '.7em',
                easeLeft: 'linear',
                easeRight: 'linear',
                imagePath: '/js/infinitecarousel/images/',
                inView: 1,
                padding: '0px',
                advance: 1,
                showControls: true,
                autoHideControls: false,
                autoHideCaptions: false,
                autoStart: true,
                prevNextInternal: true,
                enableKeyboardNav: true,
                onSlideStart: function(){},
                onSlideEnd: function(){},
                onPauseClick: function(){},
                onThumbClick: function(){}
            };
            var options = $jq.extend(defaults, options);
	
            return this.each(function() {
                var randID = Math.round(Math.random()*100000000);
                var o=options;
                var obj = $jq(this);
                var autopilot = o.autoStart;

                var numImages = $jq('img', obj).length; // Number of images
                var imgHeight = $jq('img:first', obj).height();
                var imgWidth = $jq('img:first', obj).width();
                        
                //eca
                if(numImages < o.inView){
                    o.inView = numImages;
                    o.advance = 1;
                }

                if(o.inView > numImages-1) o.inView=numImages-1; // check to make sure inview isnt greater than the number of images. inview should be at least two less than numimages (otherwise hinting wont work and animating left may catch a flash), but one less can work
                        
                //eca
                singleView = false;
                if(o.inView == 0){
                    o.inView = 1;
                    autopilot = false;
                    singleView = true;
                }
                        
                $jq('p', obj).hide(); // Hide any text paragraphs in the carousel
                $jq(obj).css({
                    'position':'relative',
                    'overflow':'hidden'
                }).width((imgWidth*o.inView)+(o.inView*parseInt(o.padding)*2)).height(imgHeight+(parseInt(o.padding)*2)); //,'overflow':'hidden'
                $jq('ul', obj).css({
                    'list-style':'none',
                    'margin':'0',
                    'padding':'0',
                    'position':'relative'
                }).width(imgWidth*numImages);
                $jq('li', obj).css({
                    'display':'inline',
                    'float':'left',
                    'padding':o.padding
                    });

                //eca
                if(!singleView){
                    // Move rightmost image over to the left
                    $jq('li:last', obj).prependTo($jq('ul', obj));
                    $jq('ul', obj).css('left',-imgWidth-(parseInt(o.padding)*2)+'px').width(9999);
                }

                // Build progress bar
                if(o.displayProgressBar)
                {
                    $jq(obj).append('<div id="progress'+randID+'" class="ic-progress-bar" style="position:absolute;bottom:0;background:#bbb;left:0;z-index:1"></div>');
                    $jq('#progress'+randID).width('100%').height(5).css('opacity','.6');
                }

                // Animate progress bar
                function startProgressBar(barTime)
                {
                    barTime = (barTime==null)? o.displayTime:barTime;
                    $jq('#progress'+randID).width('100%').height(5);
                    $jq('#progress'+randID).animate({
                        'width':0
                    },barTime);
                }

                // Build textholder div(s) as wide as one image and as tall as the textholderHeight option
                var containerBorder = parseInt($jq(obj).css('border-bottom-width')) + parseInt($jq(obj).css('border-top-width'));
                if(isNaN(containerBorder)) containerBorder = 0; // IE returns NaN for $jq(obj).css('border-bottom-width')
                var containerPaddingLeft = parseInt($jq(obj).css('padding-left')); // Normally we'd do both left and right but only left matters here
                for(i=1;i<=o.inView;i++)
                {
                    $jq(obj).append('<div id="textholder'+randID+'_'+i+'" class="textholder" style="position:absolute;width:'+imgWidth+'px;bottom:0px;margin-bottom:'+-(imgHeight*o.textholderHeight+containerBorder)+'px;"><span></span></div>');
                    $jq('#textholder'+randID+'_'+i).css({
                        'left':(i-1)*(imgWidth+parseInt(o.padding)*2),
                        'margin-left':parseInt(o.padding)+containerPaddingLeft,
                        'margin-right':o.padding
                        });
                    $jq('#textholder'+randID+'_'+i).height(imgHeight*o.textholderHeight).css({
                        'backgroundColor':'#FFF',
                        'opacity':'0.5'
                    });
                    html = '<div class="minmax" id="minmax'+randID+'_'+i+'" style="width:8px;height:8px;position:absolute;top:1px;right:10px;cursor:pointer;background:url('+o.imagePath+'caption.gif) no-repeat 0 -8px"></div>';
                    html += '<div class="close" id="close'+randID+'_'+i+'" style="width:8px;height:8px;position:absolute;top:1px;right:1px;cursor:pointer;background:url('+o.imagePath+'caption.gif) no-repeat 0 0"></div>';
                    $jq('#textholder'+randID+'_'+i).append(html);
                    $jq('#minmax'+randID+'_'+i).hide();
                    $jq('#close'+randID+'_'+i).hide();
                    if(!o.autoHideCaptions) showtext($jq('li:eq('+i+') p', obj).html(),i);
                }
                var textholderPadding = parseInt($jq('#textholder'+randID+'_1').css('padding-left')) + parseInt($jq('#textholder'+randID+'_1').css('padding-right'));
                if (textholderPadding > 0) $jq('.textholder',obj).width(imgWidth-textholderPadding);

                $jq('.close',obj).each(function(i){ // Need to use each() because a loop doesn't work in this situation. see http://www.bennadel.com/blog/534-The-Beauty-Of-The-jQuery-Each-Method.htm
                    $jq(this).click(function(){
                        $jq('#textholder'+randID+'_'+(i+1)).animate({
                            marginBottom:(-imgHeight*o.textholderHeight)-containerBorder-1+'px'
                            },500)
                        });
                });
                $jq('.minmax',obj).each(function(i){ // Same reason as previous chunk
                    $jq(this).click(function(){
                        if(parseInt($jq('#textholder'+randID+'_'+(i+1)).css('margin-bottom'))==0)
                        {
                            $jq('#textholder'+randID+'_'+(i+1)).animate({
                                marginBottom:((-imgHeight*o.textholderHeight)-containerBorder+12)+'px'
                                },500,function(){
                                $jq('#minmax'+randID+'_'+(i+1)).css('background-position','0 -16px')
                                });
                        }
                        else
                        {
                            $jq('#textholder'+randID+'_'+(i+1)).animate({
                                marginBottom:'0px'
                            },500,function(){
                                $jq('#minmax'+randID+'_'+(i+1)).css('background-position','0 -8px')
                                });
                        }

                    });
                });

                function showtext(t,i)
                {
                    if(autopilot)
                    {
                        $jq('#minmax'+randID+'_'+i).hide();
                        $jq('#close'+randID+'_'+i).hide();
                    }
                    if(t != null)
                    {
                        $jq('#textholder'+randID+'_'+i+' span').html(t); // Change textholder content
                        $jq('#textholder'+randID+'_'+i).stop().animate({
                            marginBottom:'0px'
                        },500); // Raise textholder
                        $jq('#minmax'+randID+'_'+i).css('background-position','0 -8px');
                        showminmax();
                    }
                }

                function showminmax()
                {
                    if(!autopilot)
                    {
                        $jq('.minmax',obj).fadeIn(250);
                        $jq('.close',obj).fadeIn(250);
                    }
                }

                function hideCaption() {
                    $jq('.textholder',obj).stop().animate({
                        marginBottom:(-imgHeight*o.textholderHeight-containerBorder-1)+'px'
                        },o.transitionSpeed)
                    }

                if(o.displayThumbnails)
                {
                    function thumbclick(event)
                    {
                        o.onThumbClick.call(this);
                        
                        target_num = this.id.split('_'); // we want target_num[1]
                        if(viewable[0] != target_num[1])
                        {
                            status='pause';
                            $jq('#progress'+randID).stop().fadeOut();
                            clearTimeout(clearInt);
                            $jq('#thumbs'+randID+' div').css({
                                'cursor':'default'
                            }).unbind('click'); // Unbind the thumbnail click event until the transition has ended
                            autopilot = 0;
                            setTimeout(function(){
                                $jq('#play_pause_btn'+randID).css('background-position','0 -16px')
                                },o.transitionSpeed);
                            $jq('#play_pause_btn'+randID).unbind('click').bind('click',function(){
                                forceStart();
                            });
                        }
                        if(target_num[1] > viewable[0])
                        {
                            diff = target_num[1] - viewable[0];
                            moveLeft(diff);
                        }
                        if(target_num[1] < viewable[0])
                        {
                            diff = viewable[0]- target_num[1];
                            moveRight(diff);
                        }
                    }

                    var viewable = []; // track which images are being displayed
                    var unviewable = []; // track which images are being displayed
                    // Build thumbnail viewer and thumbnail divs
                    $jq(obj).after('<div id="thumbs'+randID+'" style="position:relative;overflow:auto;clear:left;text-align:left;padding-top:5px;"></div>');
                    for(i=0;i<=numImages-1;i++)
                    {
                        thumb = $jq('img:eq('+(i+1)+')', obj).attr('src');
                        $jq('#thumbs'+randID).append('<div class="thumb" id="thumb'+randID+'_'+(i+1)+'" rel="'+(i+1)+'" style="cursor:pointer;background-image:url('+thumb+');display:inline;float:left;width:'+o.thumbnailWidth+';height:'+o.thumbnailHeight+';line-height:'+o.thumbnailHeight+';padding:0;overflow:hidden;text-align:center;border:2px solid #ccc;margin-right:4px;font-size:'+o.thumbnailFontSize+';font-family:Arial;color:#000;text-shadow:0 0 3px #fff">'+(i+1)+'</div>');
                        if(i<=o.inView) $jq('#thumb'+randID+'_'+i).css({
                            'border-color':'#ff0000'
                        });
                        unviewable.push(i+1);
                    }
                    // Initialize viewable/unviewable arrays
                    for(i=1;i<=o.inView;i++) viewable.push(unviewable.shift());

                    // Next two lines are a special case to handle the first list element which was originally the last
                    thumb = $jq('img:first', obj).attr('src');
                    $jq('#thumb'+randID+'_'+numImages).css({
                        'background-image':'url('+thumb+')'
                        });
                    $jq('#thumbs'+randID+' div.thumb:not(:first)').css({
                        opacity:.65
                    }); // makes all thumbs 65% opaque except the first one

                    $jq('#thumbs'+randID+' div.thumb').hover(function(){
                        $jq(this).animate({
                            'opacity':1
                        },150)
                        },function(){
                        if(viewable[0]!=this.id.split('_')[1]) $jq(this).animate({
                            'opacity':.65
                        },250)
                        }); // add hover to thumbs
                    // Assign click handler for the thumbnails. Normally the format $jq('.thumb') would work but since it's outside of our object (obj) it would get called multiple times
                    $jq('#thumbs'+randID+' div').bind('click', thumbclick); // We use bind instead of just plain click so that we can repeatedly remove and reattach the handler
				
                    if(!o.displayThumbnailNumbers) $jq('#thumbs'+randID+' div').text('');
                    if(!o.displayThumbnailBackground) $jq('#thumbs'+randID+' div').css({
                        'background-image':'none'
                    });
                }

                if(o.showControls)
                {
                    // Pause/play button(img)
                    html = '<div id="play_pause_btn'+randID+'" style="cursor:pointer;position:absolute;top:3px;right:3px;border:none;width:16px;height:16px;background:url('+o.imagePath+'playpause.gif) no-repeat 0 0"></div>';
                    $jq(obj).append(html);
                    var status = 'play';
                    $jq('#play_pause_btn'+randID).css('opacity',.5).hover(function(){
                        $jq(this).animate({
                            opacity:'1'
                        },250)
                        },function(){
                        $jq(this).animate({
                            opacity:'.5'
                        },250)
                        });
                    $jq('#play_pause_btn'+randID).click(function(){
                        status = (status == 'play') ? 'pause':'play';
                        (status=='play') ? forceStart():forcePause();
                    });

                    if(!o.prevNextInternal)
                    {
                        wrapID = $jq(obj).attr('id')+'Wrapper';
                        $jq(obj).wrap('<div id="'+wrapID+'"></div>').css('margin','0 auto');
                        $jq('#'+wrapID).css('position','relative').width(($jq(obj).width()+40+parseInt($jq(obj).css('padding-left'))+parseInt($jq(obj).css('padding-right'))));
                    }

                    // Prev/next button(img)
                    arrowsTop = ((imgHeight/2)-15)+parseInt(o.padding);
                    html = '<div id="btn_rt'+randID+'" style="position:absolute;right:2px;top:'+arrowsTop+'px;cursor:pointer;border:none;width:13px;height:30px;background:url('+o.imagePath+'leftright.gif) no-repeat 0 0"></div>';
                    html += '<div id="btn_lt'+randID+'" style="position:absolute;left:2px;top:'+arrowsTop+'px;cursor:pointer;border:none;width:13px;height:30px;background:url('+o.imagePath+'leftright.gif) no-repeat -13px 0"></div>';
                    (o.prevNextInternal) ? $jq(obj).append(html):$jq('#'+wrapID).append(html);

                    $jq('#btn_rt'+randID).css('opacity',.5).click(function(){
                        forcePrevNext('next');
                    }).hover(function(){
                        $jq(this).animate({
                            opacity:'1'
                        },250)
                        },function(){
                        $jq(this).animate({
                            opacity:'.5'
                        },250)
                        });
                    $jq('#btn_lt'+randID).css('opacity',.5).click(function(){
                        forcePrevNext('prev');
                    }).hover(function(){
                        $jq(this).animate({
                            opacity:'1'
                        },250)
                        },function(){
                        $jq(this).animate({
                            opacity:'.5'
                        },250)
                        });

                    if(o.autoHideControls && o.prevNextInternal)
                    {
                        function showcontrols()
                        {
                            $jq('#play_pause_btn'+randID).stop().animate({
                                top:'3px',
                                right:'3px'
                            },250);
                            $jq('#btn_rt'+randID).stop().animate({
                                top:arrowsTop+'px',
                                right:'2px'
                            },250);
                            $jq('#btn_lt'+randID).stop().animate({
                                top:arrowsTop+'px',
                                left:'2px'
                            },250);
                        }
                        function hidecontrols()
                        {
                            $jq('#play_pause_btn'+randID).stop().animate({
                                top:-16-containerBorder+'px',
                                right:-16-containerBorder+'px'
                                },250);
                            $jq('#btn_rt'+randID).stop().animate({
                                right:'-16px'
                            },250);
                            $jq('#btn_lt'+randID).stop().animate({
                                left:'-16px'
                            },250);
                        }
                        $jq(obj).hover(showcontrols,hidecontrols);
                        hidecontrols();
                    }
                    if(o.autoHideCaptions)
                    {
                        var isHover;
                        function autoShowCap(){
                            isHover=true;
                            for(i=1;i<=o.inView;i++) showtext($jq('li:eq('+i+') p', obj).html(),i);
                        }
                        function autoHideCap(){
                            isHover=false;
                            hideCaption();
                        }
                        $jq(obj).hover(autoShowCap,autoHideCap);
                        hideCaption();
                    }
                }

                function keyBind(){
                    if(o.enableKeyboardNav)
                    {
                        $jq(document).keydown(function(event){
                            if(event.keyCode == 39)
                            {
                                forcePrevNext('next');
                                $jq(document).unbind('keydown');
                            }
                            if(event.keyCode == 37)
                            {
                                forcePrevNext('prev');
                                $jq(document).unbind('keydown');
                            }
                            if(event.keyCode == 80 || event.keyCode == 111) forcePause();
                            if(event.keyCode == 83 || event.keyCode == 115)
                            {
                                forceStart();
                                $jq(document).unbind('keydown');
                            }
                        });
                    }
                }

                function forcePrevNext(dir)
                {
                    o.onPauseClick.call(this);
                    $jq('#btn_rt'+randID).unbind('click');
                    $jq('#btn_lt'+randID).unbind('click');
                    setTimeout(function(){
                        $jq('#play_pause_btn'+randID).css('background-position','0 -16px')
                        },o.transitionSpeed-1);
                    autopilot = 0;
                    $jq('#progress'+randID).stop().fadeOut();
                    status='pause';
                    clearTimeout(clearInt);
                    (dir=='prev') ? moveRight():moveLeft();
                    $jq('#play_pause_btn'+randID).unbind('click');
                    setTimeout(function(){
                        $jq('#play_pause_btn'+randID).bind('click',function(){
                            forceStart();
                        });
                        $jq('#btn_rt'+randID).bind('click',function(){
                            forcePrevNext('next')
                            });
                        $jq('#btn_lt'+randID).bind('click',function(){
                            forcePrevNext('prev')
                            });
                    },o.transitionSpeed);
                }

                function forcePause()
                {
                    $jq('#play_pause_btn'+randID).unbind('click'); // unbind the click, wait for transition, then reenable
                    if(autopilot)
                    {
                        o.onPauseClick.call(this);
                        $jq('#play_pause_btn'+randID).fadeTo(250,0,function(){
                            $jq(this).css({
                                'background-position':'0 -16px',
                                'opacity':'.5'
                            });
                        }).animate({
                            opacity:.5
                        },250);
                        autopilot = 0;
                        showminmax();
                        $jq('#progress'+randID).stop().fadeOut();
                        clearTimeout(clearInt);
                        setTimeout(function(){
                            $jq('#play_pause_btn'+randID).bind('click',function(){
                                forceStart();
                            })
                            },o.transitionSpeed);
                    }
                }

                function forceStart()
                {
                    $jq('#play_pause_btn'+randID).unbind('click'); // unbind the click, wait for transition, then reenable
                    if(!autopilot)
                    {
                        setTimeout(function(){
                            $jq('#play_pause_btn'+randID).css('background-position','0 0')
                            },o.transitionSpeed-1);
                        autopilot = 1;
                        moveLeft();
                        clearInt=setInterval(function(){
                            moveLeft();
                        },o.displayTime+o.transitionSpeed);
                        setTimeout(function(){
                            $jq('#play_pause_btn'+randID).bind('click',function(){
                                forcePause();
                            })
                            },o.transitionSpeed);
                    }
                }

                function preMove()
                {
                    hideCaption();
                    // Fade out play/pause/left/right
                    if(o.showControls && o.prevNextInternal)
                    {
                        $jq('#play_pause_btn'+randID).fadeOut(200);
                        $jq('#btn_lt'+randID).fadeOut(200);
                        $jq('#btn_rt'+randID).fadeOut(200);
                    }
                    if(o.displayThumbnails) for(i=1;i<=numImages;i++) $jq('#thumb'+randID+'_'+i).css({
                        'border-color':'#ccc'
                    }).animate({
                        'opacity': .65
                    },500);
                }

                function postMove()
                {
                    if(o.showControls && o.prevNextInternal)
                    {
                        $jq('#play_pause_btn'+randID).fadeIn(200);
                        $jq('#btn_lt'+randID).fadeIn(200);
                        $jq('#btn_rt'+randID).fadeIn(200);
                    }
                    keyBind();
                    if(o.autoHideCaptions && isHover) autoShowCap();
                    if(o.displayThumbnails) for(i=0;i<viewable.length;i++) $jq('#thumb'+randID+'_'+viewable[i]).css({
                        'border-color':'#ff0000'
                    }).animate({
                        'opacity': 1
                    },500);
                    if(!o.autoHideCaptions) for(i=1;i<=o.inView;i++) showtext($jq('li:eq('+i+') p', obj).html(),i);
                    if(o.displayThumbnails) $jq('#thumbs'+randID+' div').unbind('click').bind('click', thumbclick).css({
                        'cursor':'pointer'
                    });
                    ary=[];
                    for(x=1;x<=o.inView;x++){
                        ary.push($jq('img:eq('+x+')',obj).attr('src'))
                        }
                    o.onSlideEnd.call(this,ary);
                }

                function moveLeft(dist)
                {
                    if(dist==null) dist=o.advance;
                    preMove();
                    if(o.displayThumbnails)
                    {
                        for(i=1;i<=dist;i++){
                            viewable.push(unviewable.shift());
                            unviewable.push(viewable.shift());
                        }
                    }
                    if(o.displayTime == 0){
                        clearInterval(clearInt);
                    } // If running a contonuous show with no display time, fist clear the interval. Then below, recursively call moveLeft
                    $jq('li:lt('+dist+')', obj).clone(true).insertAfter($jq('li:last', obj)); // Copy the first image (offscreen to the left) to the end of the list (offscreen to the right)
                    o.onSlideStart.call(this,viewable,'left');
                    $jq('ul', obj).animate({
                        left:-imgWidth*(dist+1)-(parseInt(o.padding)*(dist+1))*2
                        },o.transitionSpeed,o.easeLeft,function(){ // Animate the entire list to the left
                        $jq('li:lt('+dist+')', obj).remove(); // When the animation finishes, remove the first image (on the left). It has already been copied to the end of the list (right)
                        $jq(this).css({
                            'left':-imgWidth-parseInt(o.padding)*2
                            });
                        if(o.displayProgressBar && autopilot) startProgressBar();
                        postMove();
                        if(o.displayTime == 0){
                            moveLeft();
                        }
                    });
                }
                function moveRight(dist)
                {
                    if(dist==null) dist=o.advance;
                    preMove();
                    if(o.displayThumbnails)
                    {
                        for(i=1;i<=dist;i++){
                            viewable.unshift(unviewable.pop());
                            unviewable.unshift(viewable.pop());
                        }
                    }
                    $jq('li:gt('+(numImages-(dist+1))+')', obj).clone(true).insertBefore($jq('li:first', obj)); // Copy rightmost (last) li and insert it after the first li
                    o.onSlideStart.call(this,viewable,'right');
                    $jq('ul', obj).css('left',-(imgWidth*(dist+1))-(parseInt(o.padding)*((dist+1)*2)))
                    .animate({
                        left:-imgWidth-(parseInt(o.padding)*2)
                        },o.transitionSpeed,o.easeRight,function(){
                        $jq('li:gt('+(numImages-1)+')', obj).remove();
                        postMove();
                    });
                }

                // Kickoff the show
                if(autopilot)
                {
                    var clearInt = setInterval(function(){
                        moveLeft();
                    },o.displayTime+o.transitionSpeed);
                    if(o.displayProgressBar) startProgressBar(o.displayTime+o.transitionSpeed);
                } else {
                    status='pause';
                    $jq('#play_pause_btn'+randID).css({
                        'background-position':'0 -16px'
                    });
                }
                keyBind();
            });
        }
    });
})(jQuery);
