var GalleryPreview = new Class({
    initialize: function(el, thumb, options) {
        this.element = $(el);
        this.img;
        this.slides = [];
        this.thumb = $(thumb);
        this.current = null;
        this.caption = null;
        this.ptr = 0;
        this.active = true;
        this.autoplay = true;
        this.timer = null;
        this.images = 0;
        this.options = {
            fade: 500,
            delay: 9000,
            width: 451,
            height: 304,
            offset: 12
        };
        loop = 0;
        this.element.set('html', '');
        $$('.thumbnail a', this.thumb).each(function(thumb) {
            this.images++;
            thumb.loop = loop;
            thumb.addEvent('click', function(e) {
                e = new Event(e).stop();
                this.goTo(thumb.loop);
            }.bindWithEvent(this));
            var img = new Element('img').addEvent('load', this.preload.bind(this))
                                        .setProperty('src', thumb.getProperty('rel'))
                                        .setProperty('alt', thumb.getElement('img').getProperty('alt'))
                                        .setStyle('position', 'absolute')
                                        .setStyle('top', '0px')
                                        .setStyle('left', '0px')
                                        .setStyle('opacity', '0')
                                        .setStyle('display', 'block')
                                        .injectInside(this.element);
            var slide = new Fx.Tween(img, {
                duration: this.options.fade,
                onComplete: this._captionUpdate.pass([false], this)
            });
            this.slides[loop] = slide;
            loop++;
        }.bind(this));
        this.captionpnl = new Element('div').setProperty('id', 'gallery_caption')
                                            .setStyle('position', 'absolute')
                                            .setStyle('height', '20px')
                                            .setStyle('overflow', 'hidden');
        this.captiontxt = new Element('div').setStyle('opacity', 0.8)
                                            .injectInside(this.captionpnl);
        this.captionpnl.fx = new Fx.Tween(this.captionpnl);
        this.captionpnl.injectInside(this.element);
    },
    
    preload: function() {
        this.images--;
        if (this.images < 1) {
            this.start();
        }
    },
    
    start: function() {
        this._reset();
        this.active = true;
        this.next();
    },
    
    stop: function() {
        this._reset();
        this.slides[this.ptr].stop();
        this.active = false;
    },
    
    next: function() {
        if (this.current) {
            this.current.start('opacity', 0);
        }
        this.current = this.slides[this.ptr];
        this.caption = this.slides[this.ptr].element.alt;
        var w = (this.current.element.width) ? this.current.element.width : this.options.width;
        var h = (this.current.element.height) ? this.current.element.height : this.options.height;

        var wd = (this.element.getCoordinates().width) ? this.element.getCoordinates().width : this.options.height;
        var ht = (this.element.getCoordinates().height) ? this.element.getCoordinates().height : this.options.height;

        var x = ((wd / 2) - (w / 2)) + 'px';
        var y = (((ht / 2) - (h / 2)) + this.options.offset) + 'px';
        this.current.element.setStyle('left', x);
        this.current.element.setStyle('top', y);
        this.current.start('opacity', 1);
        this.ptr++;
        if (this.ptr >= this.slides.length) {
            this.ptr = 0;
        }
        this._captionUpdate(true);
        if (this.autoplay) {
            this.timer = this.next.delay(this.options.delay, this);
        }
    },
    
    goTo: function(el) {
        this.ptr = el;
        this.autoplay = false;
        this.start();
    },
    
    _reset: function() {
        if (this.timer) {
            $clear(this.timer);
            this.timer = null;
        }
    },
    
    _captionUpdate: function(close) {
        this.captionpnl.fx.cancel();
        if (close) {
            if (this.caption) {
                this.captionpnl.fx.start('height', 0);
            }
        } else if (this.active && this.caption) {
            this.captiontxt.set('html', this.caption);
            this.captionpnl.fx.start('height', this.captiontxt.offsetHeight);
        }
    }
});

var GalleryCarousel = new Class({
    ctr: 0,
    max: 0,
    maxw: 0,
    width: 0,
    xpos: 0,
    ypos: 0,
    delay: 0,
    scroll: null,
    panel: null,
    tray: null,
    item: [],
    options: {
        group: 1,
        delay: 50,
        duration: 500,
        transition: Fx.Transitions.Cubic.easeOut,
        linkBack: null,
        linkNext: null,
        linkCtrl: 'linkCtrl'
    },

    initialize: function(win, options) {
        if (!$(win)) {
            return false;
        }
        
        var win = $(win);
        this.setOptions(options);
        this.panel = win.getElement('.thumbpanel');
        this.tray = win.getElement('.thumbtray');
        this.ctr = 0;
        this.maxw = 0;

        $$('.thumbnail').each(function(item) {
            this.ctr++;
            this.item[this.ctr] = {left: this.maxw,
                                   width: item.getCoordinates().width,
                                   height: item.getCoordinates().height};
            this.maxw += this.item[this.ctr].width;
        }.bind(this));

        this.ctr = 0;
        this.width = this.panel.getCoordinates().width;
        this.max = Math.floor(this.maxw / this.width);
        
        this.scroll = new Fx.Scroll(this.panel, {wait: true,
                                                 duration: this.options.duration,
                                                 transition: this.options.transition});

        this.up = new Element('p').addEvent('mouseover', this.hoverOn)
                        .addEvent('mouseout', this.hoverOff)
                        .addEvent('click', this.rewind.bindWithEvent(this))
                        .addEvent('dblclick', this.rewind.bindWithEvent(this))
                        .addClass(this.options.linkBack)
                        .setOpacity(0.5)
                        .injectInside(win)
                        .set('html', 'Back');
        this.dn = new Element('p').addEvent('mouseover', this.hoverOn)
                        .addEvent('mouseout', this.hoverOff)
                        .addEvent('click', this.advance.bindWithEvent(this))
                        .addEvent('dblclick', this.advance.bindWithEvent(this))
                        .addClass(this.options.linkNext)
                        .setOpacity(0.5)
                        .injectInside(win)
                        .set('html', 'Next');

        this.render();
    },
    
    advance: function(e) {
        e = new Event(e);
        e.stop();
        if (this.ctr == this.max) {
            return false;
        }
        
        this.ctr++;
        
        this.render();
    },
    
    rewind: function(e) {
        e = new Event(e);
        e.stop();
        if (this.ctr == 0) {
            return false;
        }
        
        this.ctr--;
        
        this.render();
    },
    
    render: function() {
        var tgt = (this.ctr * this.width > this.maxw - this.width) ? this.maxw - this.width : this.ctr * this.width;
        this.scroll.start(this.ctr * this.width, 0);
        this.up.setStyles({display: (this.ctr > 0) ? 'block' : 'none'});
        this.dn.setStyles({display: (this.ctr < this.max) ? 'block' : 'none'});
    },
    
    hoverOn: function() {
        this.tween('opacity', 1);
    },
    
    hoverOff: function() {
        this.tween('opacity', 0.5);
    }
});

GalleryCarousel.implement(new Options);
