/*
 * Slider based on Glider found at http://www.missingmethod.com/projects/glider.html
 * Chris Peery
 * version 1 2009-07-25
 */

var Scroller = Class.create();
Object.extend(Object.extend(Scroller.prototype, Abstract.prototype), {
	initialize : function(viewport, list, options) {
		this.viewport = $(viewport);
		this.list = $(list);
		this.scrolling = null;
    this.activeItemPostId = null;
		
		this.options = Object.extend({
	      beforeScroll: Prototype.emptyFunction,
	      afterScroll: Prototype.emptyFunction,
	      listHeight: 85,
	      duration: 0.5,
	      defaultListItemIndex: 0,
	      itemEvent: 'click',
	      nextItemEvent: 'click',
	      previousItemEvent: 'click',
	      nextItemId: 'next-item',
	      previousItemId: 'previous-item'
		},options || {});
		
		// define events for slider
		this.events = {
			itemClick: this.itemSelect.bind(this),
			nextClick: this.nextItem.bind(this),
			previousClick: this.previousItem.bind(this)
		};
		
		this.items = this.list.getElementsBySelector('li');
		if ( null == this.items ) return false;
		
		// add next item observers
		var nextControls = $(this.options.nextItemId);
    if ( nextControls ) Event.observe(nextControls, this.options.nextItemEvent, this.events.nextClick, false);

		// add previous item observers
		var previousControls = $(this.options.previousItemId);
    if ( previousControls ) Event.observe(previousControls, this.options.previousItemEvent, this.events.previousClick, false);
		
		// add item observers
		this.items.invoke('observe', this.options.itemEvent, this.events.itemClick);
		
		this.activeItemIndex = ( this.items.length >= this.items.defaultListItemIndex )
			? this.items.defaultListItemIndex
			: 0;
			
		this.activeItem = this.items[this.activeItemIndex];
		this.scrollToItem(this.activeItem);
	},
	itemSelect: function(event)
	{
		Event.stop(event);
		
		var element = Event.element(event);
		element.blur();
		
		if (this.scrolling) this.scrolling.cancel();
		this.activeItemIndex = this.calculateIndex(element);
		this.scrollToItem(element);	
	},
	nextItem: function(event)
	{
		Event.stop(event);
		
		var element = Event.element(event);
		if ( !element.readAttribute('href') ) element = element.up('a', 0);
		element.blur();
		
		if (this.scrolling) this.scrolling.cancel();
		var nextItemIndex = this.calculateNextItemIndex();
		this.activeItemIndex = nextItemIndex;
		this.scrollToItem(this.items[nextItemIndex]);
	},
	previousItem: function(event)
	{
		Event.stop(event);
				
		var element = Event.element(event);
		if ( !element.readAttribute('href') ) element = element.up('a', 0);
		element.blur();
		
		if (this.scrolling) this.scrolling.cancel();
		var previousItemIndex = this.calculatePreviousItemIndex();
		this.activeItemIndex = previousItemIndex;
		this.scrollToItem(this.items[previousItemIndex]);
	},
	calculateNextItemIndex: function()
	{
		if ( (this.activeItemIndex + 1) == this.items.length ) return 0;
		return this.activeItemIndex + 1;
	},
	calculatePreviousItemIndex: function()
	{
		if ( (this.activeItemIndex - 1) < 0 ) return this.items.length - 1;
		return this.activeItemIndex - 1;
	},
	calculateIndex: function(item)
	{
		this.items.each(function(element) {
			if ( element.id == options.item.id ) options.index = element.id;
		}.bind(options = {item: item, index: 0}));
		return parseInt(options.index);
	},
	setActiveItem: function(item)
	{
    this.activeItemPostId = this.getPostId(item);
		this.activeItem.removeClassName('active');
		this.activeItem = item;
		this.activeItem.addClassName('active');
	},
  getPostId: function(item)
  {
    var idParts = item.id.split(":");
    return (idParts.length == 2) ? idParts[1] : 0;
  },
	scrollToItem: function(item)
	{
	    Position.prepare();
	    var containerOffset = Position.cumulativeOffset(this.viewport);
	    var elementOffset = Position.cumulativeOffset(item);

	    this.setActiveItem(item);
	
	    this.scrolling = new Effect.SmoothScroll(this.viewport, {
        beforeStart:this.options.beforeScroll.bind(this),
        afterFinish:this.options.afterScroll.bind(this),
	    	duration:this.options.duration,
	    	x:(elementOffset[0]-containerOffset[0]),
	    	y:(elementOffset[1]-containerOffset[1])
	    });
	}
});

Effect.SmoothScroll = Class.create();
Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = $(element);
		
		var options = Object.extend({
			x: 0,
			y: 0,
			mode: 'absolute'
			} , arguments[1] || {}  );

		this.start(options);
	},
	setup: function() {
		if (this.options.continuous && !this.element._ext ) {
			this.element.cleanWhitespace();
			this.element._ext=true;
			this.element.appendChild(this.element.firstChild);
		}

		this.originalLeft=this.element.scrollLeft;
		this.originalTop=this.element.scrollTop;

		if(this.options.mode == 'absolute') {
			this.options.x -= this.originalLeft;
			this.options.y -= this.originalTop;
		} 
	},
	update: function(position) {
		this.element.scrollLeft = this.options.x * position + this.originalLeft;
		this.element.scrollTop  = this.options.y * position + this.originalTop;
	}
});
