/**
 *      slides_reel.js
 *      version 0.2
 *      
 *      rmp - revealing module pattern
 *      - a fairly simple javascript slides viewer
 *      
 *      dependencies:
 *          flTools.js - stopEvent()
 *          jQuery.js
 *
 * @author Rasmus Rasmussen & Jonas Wilson Schnack - www.floatinglogic.dk
 */
var slides_reel = function( frame, slides, thumbs )
{
    // settings
    var margin = 10;    
    var reservedLeft = 200;
    var elementOverflowTolerance = 5;
    var thumbMinMargin = 5;
    var windowMaxWidth = 1400;
    var windowMinWidth = 980;
    
    // objects
    var myFrame = frame; // = {}
    var myReel = {};
    var curtainLeft = {};
    var curtainRight = {};
    var myScrollbar = {};
    
    // arrays
    var mySlides = [];
    var myThumbs = [];
    var myInterestPoints = [];
    
    // dimensions
    var frameWidth = myFrame.width()-8;
    var reelWidth = 0;
    
    var viewableArea;    
    var curtainLeftWidth = 0;
    var curtainRightWidth = 0;
    
    // states
    var activeInterestPoint = 0;
    
    /*
     * Private methods
     */
    var update_frame_width = function()
    {
        frameWidth = myFrame.width();
    }
    
    var update_viewable_area = function()
    {
        viewableArea = frameWidth - reservedLeft;
    }
    
    
    var generate_thumbnail_slide = function()
    {
        update_viewable_area();
        
        var rowWidth = -thumbMinMargin;// to compensate for an error in first row on first page
        var rowStart = 0;
        var row = [];
        
        for( var i = 0; i < thumbs.length; ++i )
        {
            if( rowWidth + thumbs[i].width > viewableArea - ( 2 * margin ) )
            {
                row.push({'rowWidth': rowWidth, 'imageArray': thumbs.slice(rowStart, i)});
                rowWidth = thumbs[i].width;
                rowStart = i;
            }    
            else
            {
                rowWidth += thumbs[i].width + thumbMinMargin;
            }
        }
        row.push({'rowWidth': rowWidth, 'imageArray': thumbs.slice(rowStart)});
        
        var numberOfThumbSlides = Math.ceil(row.length / 4 );
        for( var i = 0; i < thumbs.length; ++i )
        {
            thumbs[i].object.attr('index', i + numberOfThumbSlides);
            thumbs[i].object.bind('click touchend', function()
            { 
                move_reel( parseInt( $(this).attr('index') ) ); 
                myScrollbar.animate_to_interest_zone( parseInt( $(this).attr('index') ) );
            });
        }
        
        for( var i = 0; i < row.length; ++i )
        {
            var line = i%4;
            if( line == 0 )
            {
                var tmb_slide = $('<div />', {'class': 'slide thumb_slide'});
                tmb_slide.css('left', reelWidth  );
                tmb_slide.css('width', viewableArea - ( 2 * margin ) );
                tmb_slide.css('height', frame.height() );
                tmb_slide.css('background-color', 'white' );
                reelWidth += viewableArea - ( 2 * margin ) + margin;
                tmb_slide.appendTo( myReel );
                mySlides.push( tmb_slide );
            }
            if( row[i].imageArray.length == 1 )
            {
                row[i].imageArray[0].object.css('left', 0);
                row[i].imageArray[0].object.css('top', line * 115);
                row[i].imageArray[0].object.appendTo( tmb_slide );
            }    
                
            else
            {
                var lineMargin = ( viewableArea - (2 * margin) - row[i].rowWidth ) / ( row[i].imageArray.length - 1 );
                
                var x = 0;
                
                for( var j = 0; j < row[i].imageArray.length; ++j )
                {
                    row[i].imageArray[j].object.css('left', Math.round(x) );
                    row[i].imageArray[j].object.css('top', line * 115);
                    x += lineMargin + row[i].imageArray[j].width + thumbMinMargin;
                    row[i].imageArray[j].object.appendTo( tmb_slide );
                }
            }
            
                
        }
    }
    
    var setup_slides = function()
    {
        for( var i = 0; i < slides.length; ++i )
        {
            slides[i].object.css('left', reelWidth );
            slides[i].object.css('width', slides[i].width );
            slides[i].object.css('height', frame.height() );
            slides[i].object.css('background-color', frame.css('background-color') );
            reelWidth += slides[i].width + margin;
            slides[i].object.appendTo( myReel );
            mySlides.push(slides[i].object);
        }
    }
    
    var setup_curtains = function()
    {
        curtainLeft = $('<div />',{'id': 'curtain_left'});
        curtainLeft.appendTo(myFrame);
        curtainRight = $('<div />',{'id': 'curtain_right'});
        curtainRight.appendTo(myFrame);
    }
    
    var draw_curtains = function()
    {
        curtainLeftWidth = ( ( frameWidth  + reservedLeft)  / 2 ) - ( myInterestPoints[ activeInterestPoint ].width / 2 );
        curtainLeft.stop();
        curtainLeft.animate({'width': curtainLeftWidth}, 200 );
        curtainRightWidth = viewableArea / 2 - ( myInterestPoints[ activeInterestPoint ].width / 2 );
        curtainRight.stop();
        curtainRight.animate({'width': curtainRightWidth}, 200 );
       
    }
    
    var calculate_interest_points = function()
    {
        update_viewable_area();
        myInterestPoints = [];
        for( var i = 0; i < mySlides.length; ++i )
        {
            var pos = - ( mySlides[i].position().left - viewableArea / 2 + mySlides[i].width() / 2 - reservedLeft );
            var diff = (frame.width() -  mySlides[i].width() + reservedLeft ) / 2;
            if( diff < reservedLeft )
                pos += reservedLeft - diff;
            myInterestPoints.push(
            {
                left:           Math.ceil( pos ),
                width:          mySlides[i].width()
            });
        }
     }
    
    /*
     * Public methods
     */
    
    var append = function()
    {
        
        myReel = $('<div />', {'id': 'reel'});
        myReel.appendTo( myFrame );
        
        if( myFrame.parent().width() > windowMaxWidth )
            myFrame.width( windowMaxWidth - 8);
        else if( myFrame.parent().width() < windowMinWidth )
            myFrame.width( windowMinWidth - 8);
        else
            myFrame.width( myFrame.parent().width() - 8);
        
        generate_thumbnail_slide();
        setup_slides();
        calculate_interest_points();
        setup_curtains();
        
        // set the initial position
        move_reel(0);
    }
    
    var remove = function()
    {
        myReel.remove();
    }
    var resize = function()
    {
        if( myFrame.parent().width() > windowMaxWidth )
            myFrame.width( windowMaxWidth - 8);
        else if( myFrame.parent().width() < windowMinWidth )
            myFrame.width( windowMinWidth - 8);
        else
            myFrame.width( myFrame.parent().width() - 8);
        
        update_frame_width();
        calculate_interest_points();
        move_reel( activeInterestPoint );
    }
    
    // transfom methods    
    var move_reel = function( slideIndex, nudge )
    {
        if( typeof nudge != "number" )
            nudge = 0;
                
        if( typeof slideIndex != "number" || slideIndex >= myInterestPoints.length || slideIndex < 0 )
            return;
        
        slideIndex = Math.floor( slideIndex );
        myReel.stop();
        myReel.animate({'left': myInterestPoints[ slideIndex ].left  + nudge}, 200 );
        
        activeInterestPoint = slideIndex;
        draw_curtains();
    }
    
    var forward = function()
    {
        if( activeInterestPoint + 1 == myInterestPoints.length )
            return;
        move_reel( activeInterestPoint +1 );
        myScrollbar.animate_to_interest_zone( activeInterestPoint );
    }
    
    var reverse = function()
    {
        if( activeInterestPoint == 0 )
            return;
        move_reel( activeInterestPoint -1 );
        myScrollbar.animate_to_interest_zone( activeInterestPoint );
    }
    
    var get_frameWidth = function()
    {
        return frameWidth;
    }
    
    var get_reelWidth = function()
    {
        return reelWidth;
    }
        
    var get_interest_points = function()
    {
        return myInterestPoints;
    }
    
    var register_scrollbar = function( scrollbar )
    {
        myScrollbar = scrollbar;
    }
    
    
    
    return{
        append              : append,
        remove              : remove,
        reverse             : reverse,
        forward             : forward,
        move_reel           : move_reel,
        resize              : resize,
        get_frameWidth      : get_frameWidth,
        get_reelWidth       : get_reelWidth,
        get_interest_points : get_interest_points,
        register_scrollbar  : register_scrollbar
    }
}
