$(function () {
    $('#post_gallery').selthPostGallery();
});

$.math = {
    cap: function (i, min, max) {
        return Math.max(min, Math.min(i, max));
    },
    loop: function (i, min, max) {
        var d = max-min;
        while (i < min) i += d;
        while (i >= max) i -= d;
        return i;
    }
};

var galleryApp;
function beforeGalleryCloseHandler() {
    $('body').triggerHandler('beforeGalleryClose');
}
function galleryCloseHandler() {
    $('body').triggerHandler('galleryClose');
}
function createGalleryFlashWidget(v, object) {
    var $this = $(v);
    var content = '<div>'+innerXHTML($this[0]).replace(/^\s+|\s+$/g, '')+'</div>';
    var $targetDiv = $('<div id="flash_alternate_'+(new Date()).getTime()+'"></div>');
    $('#container').append($('<div id="expanded_gallery"></div>').append($targetDiv));
    var id = $targetDiv.attr('id');
    swfobject.embedSWF(
        RESOURCE_PATH + "flash/SelthLightbox.swf", id, 
        "100%", "100%", 
        "0.0.0", "", 
        { // flashvars
            content: escapeIgnoringDiacritics(content),
            startWithIndex: $('#post_gallery a').index(object),
            initialRectangle: $(object).find('img').rectangle()
        }, 
        { // params
            quality: "high",
            bgcolor: "#ffffff",
            allowscriptaccess: "sameDomain",
            allowfullscreen: "true",
            wmode: "transparent"
        }, 
        { // attributes
            id: id,
            name: "SelthLightbox",
            align: "middle"
        }
    );

    var app = document.getElementById(id);
    galleryApp = app;
    (function () {
        // waits for app.addFlashEventListener to become available
        if (app.addFlashEventListener == undefined) return setTimeout(arguments.callee, 100);
        app.addFlashEventListener('galleryClose', 'galleryCloseHandler');
        app.addFlashEventListener('beforeGalleryClose', 'beforeGalleryCloseHandler');
    })();
}

$.fn.rectangle = function () {
    var offset = this.offset();
    return [ offset.left, offset.top, this.width(), this.height() ];
};

$.fn.selthPostGallery = function () {
    return this.each(function () {
        var $pg = $(this);
        var $as = $pg.find('a');
        
        var ts = new ThumbnailShuffler($pg);
        
        $as.click(function (e) {
            e.preventDefault();
            
            ts.pause();
            createGalleryFlashWidget($(this).parent()[0], this);
            
            return false;
        });
        $('body')
            .bind('beforeGalleryClose', function () {
                var i = galleryApp.getCurrentImageIndex();
                ts.setCurrentImageIndex(i);
            })
            .bind('galleryClose', function () {
                ts.resume();
                galleryApp = null;
                $('#expanded_gallery').remove();
            })
        ;
        
        var $nextButton;
        
        if ($as.size() > 1) {
            $nextButton = $('<div class="thumbnail-shuffler-next">')
                    .css({ float: 'left' })
                    .click(function () {
                        ts.next();
                    })
                ;
        }
        $pg.css({ float: 'left' }).after($nextButton);
    });
};

/**
 * ThumbnailShuffler
 */
var ThumbnailShuffler = (function () {

// Define a local copy of ThumbnailShuffler
var ThumbnailShuffler = function ( object, options ) {
        return new ThumbnailShuffler.fn.init( object, options );
    };

ThumbnailShuffler.fn = ThumbnailShuffler.prototype = {
        
        //
        init: function (object, options) {
            var self = this; // reference to use in callbacks
            var $this = this.$this = $(this); // reference to use for jQuery animation
            var $post_gallery = this.$post_gallery = object;
            var $as = this.$as = object.find('a');
            var $firstImg = this.$firstImg = $as.eq(0).find('img');
            
            if ($as.size() < 2) return;
            
            this.currentImage = 0;
            this.paused = false;
            
            $post_gallery.css({ position: 'relative', overflow: 'hidden' });
            self.resize();
            $firstImg.load(function () { self.resize(); });
            
            $as.css({ position: 'absolute', left: 0, top: 0 });
            
            this.delay(); // animation sequence starts with a delay displaying the first image
            
            return this;
        },
        
        resize: function () {
            var $post_gallery = this.$post_gallery;
            var $firstImg = this.$firstImg;
            var that = this;
            
            setTimeout(function () { // Postponing this task to make sure width() returns the correct dimensions
                $post_gallery.css({ width: $firstImg.width(), height: $firstImg.height() });
                that.reposition();
            }, 10);
            
            return this;
        },
        
        reposition: function () {
            var n = this.$as.size();
            var currentImage = $.math.loop(this.currentImage, 0, n);
            var w = this.$firstImg.width();
            if (w == 0) return this;
            this.$as.each(function (i){
                $(this).css({ 
                    left: $.math.cap(
                            $.math.loop(w*(i-currentImage), -n*w/2, n*w/2),
                            -w-1,
                            w+1
                        )
                }); 
            });
            
            return this;
        },
        
        //
        getCurrentImageIndex: function () {
            return Math.round($.math.loop(this.currentImage, 0, this.$as.size()));
        },
        
        setCurrentImageIndex: function (i) {
            this.currentImage = Math.round($.math.loop(i, 0, this.$as.size()));
            return this.reposition();
        },
        
        // 
        pause: function () {
            this.paused = true;
            this.$this.stop(true, true);
            return this;
        },
        
        //
        resume: function () {
            this.paused = false;
            return this.delay();
        },
        
        //
        next: function () {
            return this.animateTo(this.getCurrentImageIndex()+1);
        },
        
        //
        animateTo: function (i) {
            var $this = this.$this;
            $this.stop().animate(
                { currentImage: i }, 
                { 
                    step: this.animateToStep, 
                    queue: false,
                    duration: 500,
                    complete: this.animateToComplete 
                }
            );
            
            return this;
        },
        animateToStep: function () { // INTERNAL
            return this.reposition();
        },
        animateToComplete: function () { // INTERNAL
            this.currentImage = $.math.loop(this.currentImage, 0, this.$as.size()); // normalize index
            if (!this.paused) {
                var self = this;
                setTimeout(function () { self.delay(); }, 0); // queue animation callback after callstack is freed
            }
            return this.reposition();
        },
        
        //
        delay: function () {
            this.delayFakeNumber = 0;
            this.$this.stop(true, true).animate({ delayFakeNumber: 1 }, { duration: 4000, complete: this.delayComplete });
            return this;
        },
        delayComplete: function () { // INTERNAL
            if (!this.paused) {
                var self = this;
                setTimeout(function () { self.next(); }, 0); // queue animation callback after callstack is freed
            }
            return this;
        }
    };

ThumbnailShuffler.fn.init.prototype = ThumbnailShuffler.fn;

// Expose ThumbnailShuffler to the global object
return (window.ThumbnailShuffler = ThumbnailShuffler);
})();

