var Photoviewer = new Class({
    initialize: function(element){
        this.holder = $(element);
        this.duration = 1500,
        this.slides = this.holder.getElements('div.photo');
        // Vertical
        // this.thumbs = this.holder.getParent().getParent().getElements('div.thumbnails div.thumb-holder');
        // Old school
        this.thumbs = this.holder.getParent().getElements('div.thumb-holder');
        this.limit = this.slides.length;
        this.view_count = 0;
        this.current = 0;
        this.target = 0;
        this.thumb_class = 'thumb-selected';
        this.resizer_w = new Fx.Morph(element, {duration: this.duration, wait: false, transition: Fx.Transitions.Quad.easeInOut});
        this.resizer_h = new Fx.Morph(element, {duration: this.duration, wait: false, transition: Fx.Transitions.Quad.easeInOut});
        var beginEvent = function() { this.begin(); };
        var boundBeginEvent = beginEvent.bind(this);
        window.addEvent('load', boundBeginEvent);
    },

    begin: function() {
        this.morphs = new Array();
        this.effects = new Array();
        $each(this.slides, function(slide, index) {
            var thumbEvent = function(e) {
                new Event(e).stop();
                this.show(index);
            };
            var boundThumbEvent = thumbEvent.bind(this);
            var a = this.thumbs[index].getElement('a');
            a.set('href', '#');
            a.addEvent('click', boundThumbEvent);
            this.effects[index] = new Fx.Tween(slide, {property: 'opacity', duration: this.duration, wait: false, transition: Fx.Transitions.Quad.easeInOut});
            if (index > 0) this.effects[index].set(0);
        }, this);
        this.thumbs[0].addClass(this.thumb_class);
    },

    show: function(value) {
        this.target = parseInt(value);
        if (this.target == this.current) return;
        this.effects[this.target].start(1);
        this.effects[this.current].start(0);
        // Thumbs
        this.thumbs[this.target].addClass(this.thumb_class);
        this.thumbs[this.current].removeClass(this.thumb_class);
        // First and second run are special cases
        if (this.view_count == 1) this.slides[0].addClass('first-slide');
        if (this.view_count == 0) {
            var initial_dimensions = this.slides[0].getSize();
            this.resizer_w.set({'width': (initial_dimensions.x)});
            this.resizer_h.set({'height': (initial_dimensions.y)});
        }
        // Holder dimensions
        var new_dimensions = this.slides[this.target].getSize();
        var old_dimensions = this.slides[this.current].getSize();
        if (new_dimensions.x != old_dimensions.x) this.resizer_w.start({'width': new_dimensions.x});
        if (new_dimensions.y != old_dimensions.y) this.resizer_h.start({'height': new_dimensions.y});
        if ((new_dimensions.x != old_dimensions.x) || (new_dimensions.y != old_dimensions.y)) {
            // Firefox is so dumb.
            // How dumb is it?
            // So dumb you have to set the width of a div and back again just to update the
            // display; finally putting the thumbnail images where they belong.
            if (Browser.Engine.gecko) {
                (function() {
                    var parent = this.holder.getParent();
                    var parent_dimensions = parent.getSize();
                    parent.set('styles', {'width': (parent_dimensions.x - 1), 'padding-right': 1});
                    (function() { parent.set('styles', {'width': parent_dimensions.x, 'padding-right': 0}); }).delay(1);
                }).delay((this.duration + 1), this);
            }
        }
        this.current = this.target;
        this.view_count++;
    }
});

var Slideshow = new Class({
    initialize: function(element){
        this.holder = $(element);
        this.duration = {
            slide: 1500,
            show: 7500
        },
        this.duration.slideshow = this.duration.slide + this.duration.show;
        this.slides = this.holder.getElements('div.photo');
        this.limit = this.slides.length;
        this.buttons = {
            play: this.holder.getElement('div.controls ul li.play'),
            pause: this.holder.getElement('div.controls ul li.pause'),
            previous: this.holder.getElement('div.controls ul li.previous'),
            next: this.holder.getElement('div.controls ul li.next')
        };
        this.controls = this.holder.getElement('div.controls');
        this.controls.setStyles({'z-index': this.limit, 'display': 'block'});
        this.controls.setOpacity(0);
        this.controls_effect = new Fx.Tween(this.controls, {property: 'opacity', duration: 250, transition: Fx.Transitions.Quad.easeInOut});
        this.controls_opacity = 0.7;
        this.is_playing = false;
        this.current = 0;
        this.target = 0;
        var beginEvent = function() { this.begin(); };
        var boundBeginEvent = beginEvent.bind(this);
        window.addEvent('load', boundBeginEvent);
    },

    begin: function() {
        var controlsStart = function() { this.controls_effect.start(this.controls_opacity); };
        var boundControlsStart = controlsStart.bind(this);
        var controlsStop = function() { this.controls_effect.start(0); };
        var boundControlsStop = controlsStop.bind(this);
        var buttonPlay = function(e) {
            new Event(e).stop();
            this.playback(true);
        };
        var boundButtonPlay = buttonPlay.bind(this);
        var buttonPause = function(e) {
            new Event(e).stop();
            this.playback(false);
        };
        var boundButtonPause = buttonPause.bind(this);
        var buttonPrevious = function(e) {
            new Event(e).stop();
            this.proceed(-1);
        };
        var boundButtonPrevious = buttonPrevious.bind(this);
        var buttonNext = function(e) {
            new Event(e).stop();
            this.proceed(1);
        };
        var boundButtonNext = buttonNext.bind(this);
        // Holder dimensions and events
        var dimensions = this.slides[0].getSize();
        this.holder.setStyles({width: dimensions.x, height: dimensions.y});
        this.holder.addEvent('mouseenter', boundControlsStart);
        this.holder.addEvent('mouseleave', boundControlsStop);
        // Button events
        this.buttons.play.getElement('a').addEvent('click', boundButtonPlay);
        this.buttons.pause.getElement('a').addEvent('click', boundButtonPause);
        this.buttons.previous.getElement('a').addEvent('click', boundButtonPrevious);
        this.buttons.next.getElement('a').addEvent('click', boundButtonNext);
        // Slide effects
        this.effects = new Array();
        $each(this.slides, function(slide, index) {
            this.effects[index] = new Fx.Tween(slide, {property: 'opacity', duration: this.duration.slide, wait: false, transition: Fx.Transitions.Quad.easeInOut});
            if (index > 0) this.effects[index].set(0);
        }, this);
        // Start the show
        this.playback(true);
    },

    playback: function(playing) {
        $clear(this.start);
        this.is_playing = playing;
        if (this.is_playing) {
            this.buttons.play.setStyle('display', 'none');
            this.buttons.pause.setStyle('display', 'block');
            this.progress();
        } else {
            this.buttons.play.setStyle('display', 'block');
            this.buttons.pause.setStyle('display', 'none');
        }
    },

    progress: function() {
        this.start.delay(this.duration.slideshow, this);
    },

    start: function() {
        if (this.is_playing) this.proceed(1);
    },

    proceed: function(value) {
        if (!value) value = 1;
        this.target += parseInt(value);
        if (this.target >= this.limit) this.target = 0;
        if (this.target < 0) this.target = (this.limit - 1);
        this.effects[this.target].start(1);
        this.effects[this.current].start(0);
        this.current = this.target;
        if (this.is_playing) this.progress();
    }
});