var Carousel = function(el) {
    this.root = $(el);
    this.init();
}

Carousel.prototype = {
    // Carousel's root tag
    root: null,
    // Container with carousel's frames
    container: null,
    // Container's width and height in px after fixing
    width: 0,
    height: 0,

    // Initialize the carousel
    init: function() {
        this.container = this.root.down('.container');

        this.root.down('.navbar').childElements().each(function(handle) {
            handle.observe('click', function(event) {
                event.stop();
                var handle = event.element();
                if (event.element.tagName != 'LI') handle = handle.up('li');
                this.show(handle.id.substr(1, 100));
            }.bindAsEventListener(this));
        }.bind(this));
        //this.container.down('#school').observe('click', this.show.bind(this, 'articles'));
        //this.container.down('#articles').observe('click', this.show.bind(this, 'school'));
    },

    /**
     * Sets the container's size to a fixed value
     */
    fixContainer: function() {
        // set container's height to the maximum height of it's panes
        /*this.height = this.container.select('.pane').max(function(pane) {
            return pane.getDimensions().height;
        });*/
        this.height = this.container.getDimensions().height;
        this.container.style.height = this.height+'px';
        // Fixes and caches the width of the container to reuse it during the animation
        this.width = this.container.getDimensions().width;
        this.container.style.width = this.width+'px';
    },

    /**
     * Releases container's fixed parameters
     */
    releaseContainer: function() {
        this.container.style.width = 'auto';
        this.container.style.height = 'auto';
    },

    /**
     * Shows the pane with the given id
     **/
    show: function(newpane) {
        if (this._newPaneFx) {
            this._newPaneFx.setNow();
            this._curPaneFx.setNow();
            this._curPaneFx.options.onComplete();
//            this._newPaneFx = this._curPaneFx = null;

            this.completeAnimation(this._curPaneFx.element, this._newPaneFx.element);
        }

        newpane = $(newpane);
        var curpane = this.container.down('.pane.current');
        if (curpane == newpane) return; // just return if we're trying to show the already shown pane

        // Fix the container and position panes, preparing them for the animation
        this.fixContainer();
        var position = curpane.previousSiblings().include(newpane) ? 'left' : 'right';
        this.preparePane(newpane, position);
        this.preparePane(curpane);

        // Animate left or right movement
        var options = { onComplete: this.completeAnimation.bind(this, curpane, newpane) };
        if (position == 'left') {
            this._newPaneFx = new fx.Style(newpane, 'left', options).custom(-this.width, 0);
            this._curPaneFx = new fx.Style(curpane, 'left').custom(0, this.width+1);
        } else {
            this._newPaneFx = new fx.Style(newpane, 'left', options).custom(this.width+1, 0);
            this._curPaneFx = new fx.Style(curpane, 'left').custom(0, -this.width);
        }

        // If new pane's height is different from the current one - animate that height change, too
        var newheight = newpane.getDimensions().height;
        if (newheight != this.height) new fx.Style(this.container, 'height').custom(this.height, newheight);
    },

    /**
     * Prepares a given pane for the animation by making it absolutely positioned
     * and putting into required position to the left or right of the visible pane
     * if it's needed
     */
    preparePane: function(pane, position) {
        var left = 0;
        switch(position) {
            case 'left': left = -this.width; break;
            case 'right': left = this.width+1; break;
        }
        pane.setStyle({
           position: 'absolute',
           display: 'block',
           //top: '0px',
           width: /*'auto', //*/(this.width)+'px',
           left: left+'px'
        });
    },

    /**
     * Releases absolutely positioned pane back to relative one
     */
    releasePane: function(pane) {
        pane.setStyle({
           position: 'relative',
           //width: '100%',
           left: '0px'
        });
    },

    /**
     * Finalizes the animation by releasing all panes and the container and updating classes
     * of panes and their handles accordingly to the new status
     */
    completeAnimation: function(curpane, newpane) {
        curpane.hide();
        curpane.removeClassName('current');
        $('h'+curpane.id).removeClassName('current');

        newpane.show();
        newpane.addClassName('current');
        $('h'+newpane.id).addClassName('current');

        $('h'+newpane.id).nextSiblings().each( function(el) {
          el.removeClassName('before');
          el.addClassName('after');
        });
        $('h'+newpane.id).previousSiblings().each( function(el) {
          el.removeClassName('after');
          el.addClassName('before');
        });

        this.releasePane(curpane);
        this.releasePane(newpane);
        this.releaseContainer();
    }

};

document.observe('dom:loaded', function() {
    $$('.carousel').each(function(el) {
        el.carousel = new Carousel(el);
    });
});