Array.implement({
	reduce: function (fn, initial, bind) {
		var len = this.length, i = 0;
		if (len === 0 && arguments.length == 1) { return null; }
		var result = initial || this[i++];
		for (; i < len; i++) { result = fn.call(bind, result, this[i], i, this); }
		return result;
	}
});

var CyclicArray = new Class({
  initialize: function(array) {
    this.array = array;
  },
  
  fetch: function(index) {
    if(index < 0) { return(this.fetch(this.array.length - Math.abs(index))); }
    if(index >= this.array.length) { return(this.fetch(index - this.array.length)); }
    return this.array[index];
  },
  
  fetchIndex: function(index) {
    if(index < 0) { return(this.fetchIndex(this.array.length - Math.abs(index))); }
    if(index >= this.array.length) { return(this.fetchIndex(index - this.array.length)); }
    return index;
  }
});

var Carousel = new Class({
  initialize: function(element, options) {
    this.options = new Hash({
      itemWidth: 219,
      itemHeight: 166,
      eachSide: 2,
      width: 600,
      height: 200
    }).extend(options);
    this.element = element;
    this.element.setStyles({
      'overflow': 'hidden',
      'position': 'relative',
      'width': this.options.width + 'px',
      'height': this.options.height + 'px'
    });
    
    this.loadImages();
    this.setIndex(0);
    this.setupButtons();
  },

  setupButtons: function() {    
    if(this.options.leftButton) {
      this.options.leftButton.addEvent('click', function(event) {
        event.stop();
        this.setIndex(this.index-1);
      }.bindWithEvent(this));
    }
    if(this.options.rightButton) {
      this.options.rightButton.addEvent('click', function(event) {
        event.stop();
        this.setIndex(this.index+1);
      }.bindWithEvent(this));
    }
  },
  
  loadImages: function() {
    this.images = this.element.getChildren();
    this.width = this.images.reduce(function(m,n) { return m + n.getSize().x; }, 0);
    
    this.container = new Element('div', {
      'styles': {
        'display': 'block',
        'position': 'absolute',
        'height': this.options.height + 'px',
        'width': this.options.width + 'px'
      }
    });
      
    this.container.inject(this.element);
    this.images.inject(this.container);
    this.images.setStyles({
      'display':'inline'
    });
  },
  
  setIndex: function(index) {
    var current = new CyclicArray(this.images);
    this.index = current.fetchIndex(index);
    this.image = current.fetch(index);
    this.reorder();
  },
  
  reorder: function() {
    this.images.dispose();
    var chosen = [];
    var current = new CyclicArray(this.images);
    var options = this.options;

    var getWidth = function(index) {
      var i = Math.abs(index - options.eachSide);
      if(i===0) { return options.itemWidth; }
      return Math.floor(options.itemWidth * (0.8/i));
    };
    
    var getHeight = function(index) {
      var i = Math.abs(index - options.eachSide);
      if(i===0) { return options.itemHeight; }
      return Math.floor(options.itemHeight * (0.8/i));
    };
    
    var getLeft = function(index) {
      var w = getWidth(index);
      if(index == options.eachSide) { return (options.width/2) - (w/2); }
      if(index === 0) { return 0; }
      if(index == options.eachSide*2) { return options.width - w; }
      
      var l = 0;
      
      if(index < options.eachSide) {
        l = getLeft(index-1);
        return l + getWidth(index-1)/1.15;
      } else {
        l = getLeft(index+1);
        return l - (getWidth(index+1)/1.15) - w/2;
      }
    };
    
    var getTop = function(index) {
      var h = getHeight(index);
      var i = Math.abs(index - options.eachSide);
      return (options.height - (h+i*30*(i*0.3)));
    };
    
    for(var i = this.index - this.options.eachSide; i < this.index + this.options.eachSide + 1; i++) {
      chosen.push(current.fetch(i));
    }
    
    chosen = new Elements(chosen);
        
    for(var index = 0; index < chosen.length; index++) {
      var div = chosen[index];
      var w = getWidth(index);
      var h = getHeight(index);
      var x = getLeft(index);
      var y = getTop(index);
      var ei = Math.abs(index - options.eachSide);

      div.setStyles({
        'width': w + 'px',
        'height': h + 'px',
        'left': x + 'px',
        'top': y + 'px',
        'overflow': 'hidden',
        'position': 'absolute',
        'display': 'block',
        'z-index': 1000-ei
      });
      
      div.getChildren('img').setStyles({
        'width': w + 'px',
        'height': h + 'px'
      });

      for(var j = 0; j <= this.options.eachSide; j++) {
        div.getChildren('div').removeClass('size-' + j);
      }
      
      div.getChildren('div').addClass('size-' + ei);
    }
    
    chosen.inject(this.container);
    itemCount = $('.carousel div.carousel-item').length;
    if (itemCount >= 3) {
      $('#carousel-text').html($('.carousel div.carousel-item:nth-child(3) span.title').html());
    } else {
      $('#carousel-text').html($('.carousel div.carousel-item:last span.title').html());
    }
  }
});

var carousel;

window.addEvent('load', function() {
  $$('.carousel').each(function(item) {
    carousel = new Carousel(item, {
      leftButton: item.getParent('.carousel-home').getElement('.carousel-left'),
      rightButton: item.getParent('.carousel-home').getElement('.carousel-right')
    });
    item.setStyle('display', 'block');
  });
});
