
var ezSlideShow = new Class(
{
    Implements: [Options, Events],

    options:
    {
        width:      1000,
        delay:      20,
        duration:   100,
        autoplay:   false,
        firstSlide: 0,
        selector:   '.slide',
    },

    initialize: function( elementId, options )
    {
        this.container = $(elementId);
        this.setOptions(options);

        this.timerId = 0;
        this.currentSlide = this.options.firstSlide;

        this.initSlides();
        this.initArrows();

        this.fireEvent('onSlideChange', ['first', this.currentSlide], 0);
    },

    initSlides: function()
    {
        this.slides = this.container.getElements(this.options.selector);
        this.slides.each(function( slide, index )
        {
            slide.setStyles({'left': (index == this.currentSlide) ? 0 : this.options.width});

            slide.store('fx', new Fx.Morph(slide, {duration: 500, transition: Fx.Transitions.Sine.easeOut}));
        }, this);

        this.resetPeriodical();
    },

    initArrows: function()
    {
        this.prevArrow = this.container.getElement('.prev');
        this.nextArrow = this.container.getElement('.next');
        if( this.prevArrow ) this.prevArrow.addEvent('click', this.prevSlide.bind(this));
        if( this.nextArrow ) this.nextArrow.addEvent('click', this.nextSlide.bind(this));
    },

    nextSlide: function()
    {
        var nextSlide = (this.currentSlide == this.slides.length - 1) ? 0 : this.currentSlide + 1;
        this.slides[this.currentSlide].retrieve('fx').start({'left': [0, -this.options.width]});
        this.slides[nextSlide].retrieve('fx').start({'left': [this.options.width, 0]});
        this.currentSlide = nextSlide;

        this.clearPeriodical();
        this.resetPeriodical();

        this.fireEvent('onSlideChange', ['next', this.currentSlide], 0);
    },

    prevSlide: function()
    {
        var prevSlide = (this.currentSlide == 0) ? this.slides.length - 1 : this.currentSlide - 1;
        this.slides[this.currentSlide].retrieve('fx').start({'left': [0, this.options.width]});
        this.slides[prevSlide].retrieve('fx').start({'left': [-this.options.width, 0]});
        this.currentSlide = prevSlide;

        this.clearPeriodical();
        this.resetPeriodical();

        this.fireEvent('onSlideChange', ['prev', this.currentSlide], 0);
    },

    clearPeriodical: function()
    {
        $clear(this.timerId);
    },

    resetPeriodical: function()
    {
        if( this.options.autoplay )
            this.timerId = this.nextSlide.periodical(this.options.delay, this);
    }
});

var ezBubbleTips = new Class(
{
    Implements: [Options, Events],

    options:
    {
    },

    initialize: function( elementSelector, options )
    {
        this.tips = document.getElements(elementSelector);
        this.setOptions(options);

        this.timerId = 0;

        this.initTips();
    },

    initTips: function()
    {
        this.tips.each(function( tip )
        {
            tip.addEvents(
            {
                'mouseenter': this._tipHover(tip, 'over'),
                'mouseleave': this._tipHover(tip, 'out')
            });
        }, this);
    },
    _tipHover: function( tip, state ){ return function(){ this.tipHover(tip, state); }.bind(this); },

    tipHover: function( tip, state )
    {
        var marker = tip.getElement('.tip-marker'), content = tip.getElement('.tip-content');
        if( !marker || !content ) return;

        switch( state )
        {
            case 'over':
                tip.addClass('open');
                marker.setStyles({'display': 'none'});
                content.setStyles({'display': 'block'});
                this.fireEvent('onShow', 0);
                break;

            case 'out':
                tip.removeClass('open');
                marker.setStyles({'display': 'block'});
                content.setStyles({'display': 'none'});
                this.fireEvent('onHide', 0);
                break;
        }
    }
});
