var Slider = Class.create();
Slider.prototype = {
    options: {
        layout: 'list', // 'list' or 'grid' values are available
        duration: 0.4,
        visible: 3,     // this is also the number of columns for 'grid' listing type
        shift: 0        // default value rewrites in constuctor
    },
    
    elements: {
        container: $('slider'), // required *
        shiftLeft: '',          // required *
        shiftRight: '',         // required *
        toggleLayout: '',       // optional
        toggleGrid: '',         // optional
        toggleList: ''          // optional
    },
    
    initialize: function(elements, options)
    {
        this.animating = false;
        this.elements.containerSize = {
            width: $(elements.container).offsetWidth,
            height: $(elements.container).offsetHeight
        }
        
        Object.extend(this.elements, elements);
        
        this.options.shift = this.elements.container.getElementsBySelector('li.slider-item')[0].offsetWidth * this.options.visible;
        
        Object.extend(this.options, options);
        
        if (this.options.layout == 'list')
            this.prepareListLayout();
            
        this.initControls();
    },
    
    toggleLayout: function()
    {
        if (this.options.layout == 'grid')
            this.prepareListLayout();
        else
            this.prepareGridLayout();
    },
    
    prepareListLayout: function()
    {
        if (typeof this.elements.toggleList == 'object')
            this.elements.toggleList.addClassName('active');
        if (typeof this.elements.toggleGrid == 'object')
            this.elements.toggleGrid.removeClassName('active');
            
        this.showControls();
        this.options.layout = 'list';
        var wrapper;
        
        wrapper = new Element('ul', {
            'class': this.elements.container.getElementsBySelector('ul')[0].readAttribute('class')
        });
        
        this.elements.container.getElementsBySelector('li.slider-item').each(function(el, index){
            wrapper.insert(el);
        })
        
        this.elements.container.getElementsBySelector('ul').each(function(el, index){
            el.remove();
        })
        
        this.elements.container.insert(wrapper);
        
        this.elements.container.setStyle({
            width:  this.elements.container.getElementsBySelector('li.slider-item')[0].offsetWidth * this.options.visible + 'px',
            height: this.elements.container.getElementsBySelector('li.slider-item')[0].offsetHeight + 20 + 'px',
            position: 'relative',
            overflow: 'hidden'
        });
        wrapper.setStyle({
            width: '10000px'
        })
        this.updateControls(1, 0);
    },
    
    prepareGridLayout: function()
    {
        if (typeof this.elements.toggleGrid == 'object')
            this.elements.toggleGrid.addClassName('active');
        if (typeof this.elements.toggleList == 'object')
            this.elements.toggleList.removeClassName('active');
            
        this.hideControls();
        this.options.layout = 'grid';
        
        var that = this;
        var wrapper;
        this.elements.container.getElementsBySelector('li.slider-item').each(function(el, index){
            if (index % that.options.visible == 0)
                wrapper = new Element('ul', {'class': that.elements.container.down().readAttribute('class')});
            wrapper.insert(el);
            that.elements.container.insert(wrapper);
        })
        this.elements.container.writeAttribute('style', '');
        this.elements.container.down().remove();
    },
    
    initControls: function()
    {
        this.elements.shiftLeft.href = this.elements.shiftRight.href = 'javascript:void(0)';
        
        Event.observe(this.elements.shiftLeft, 'click', this.shiftLeft.bind(this));
        Event.observe(this.elements.shiftRight, 'click', this.shiftRight.bind(this));
            
        if (typeof this.elements.toggleLayout == 'object') {
            this.elements.toggleLayout.href = 'javascript:void(0)';
            Event.observe(this.elements.toggleLayout, 'click', this.toggleLayout.bind(this));
        }
        
        if (typeof this.elements.toggleGrid == 'object') {
            this.elements.toggleGrid.href = 'javascript:void(0)';
            Event.observe(this.elements.toggleGrid, 'click', this.prepareGridLayout.bind(this));
        }
        
        if (typeof this.elements.toggleList == 'object') {
            this.elements.toggleList.href = 'javascript:void(0)';
            Event.observe(this.elements.toggleList, 'click', this.prepareListLayout.bind(this));
        }
            
        this.updateControls(1, 0);
    },
    
    shiftRight: function()
    {
        if (this.animating || this.options.layout != 'list')
            return;
        
        var left = isNaN(parseInt(this.elements.container.down().style.left)) ? 0 : parseInt(this.elements.container.down().style.left);
        
        if ((left + this.options.shift) < 0) {
            var shift = this.options.shift;
            this.updateControls(1, 1);
        } else {
            var shift = Math.abs(left);
            this.updateControls(1, 0);
        }
        this.moveTo(shift);
    },
    
    shiftLeft: function()
    {
        if (this.animating || this.options.layout != 'list')
            return;
        
        var left = isNaN(parseInt(this.elements.container.down().style.left)) ? 0 : parseInt(this.elements.container.down().style.left);
        
        var lastItemLeft = this.elements.container.down().childElements().last().positionedOffset()[0];
        var lastItemWidth = this.elements.container.down().childElements().last().offsetWidth;
        var contentWidth = lastItemLeft + lastItemWidth + 8;
        
        if ((contentWidth + left - this.options.shift) > this.elements.containerSize.width) {
            var shift = this.options.shift;
            this.updateControls(1, 1);
        } else {
            var shift = contentWidth + left - this.elements.containerSize.width;
            this.updateControls(0, 1);
        } 
        this.moveTo(-shift);
    },
    
    moveTo: function(shift)
    {
        var scope = this;
                     
        this.animating = true;
        
        new Effect.Move(this.elements.container.down(), {
            x: shift,
            duration: this.options.duration,
            delay: 0,
            afterFinish: function(){
                scope.animating = false;
            }
        });
    },
    
    updateControls: function(left, right)
    {
        if (!left)
            this.elements.shiftLeft.addClassName('disabled');
        else
            this.elements.shiftLeft.removeClassName('disabled');
        
        if (!right)
            this.elements.shiftRight.addClassName('disabled');
        else
            this.elements.shiftRight.removeClassName('disabled');
    },
    
    hideControls: function()
    {
        this.elements.shiftRight.hide();
        this.elements.shiftLeft.hide();
    },
    
    showControls: function()
    {
        this.elements.shiftRight.show();
        this.elements.shiftLeft.show();
    }
}