

InfiniteScroll = new Class({

	Implements: [Options, Events],
	
	options: {
		childType: 'li',
		move: 'left',
		padding: 0,
		offset: 0
	},

	initialize: function(el, opts){
	
		// set options
		this.setOptions(opts);
		
		// store refs
		this.el = el;
						
		this.children = this.el.getElements(this.options.childType);
						
		// set styles on el
		this.el.setStyles({
			position: 'relative',
			overflow: 'hidden'
		});
	
		// call reset to set initial positions
		this.reset();
	
	},
	
	// set initial positions
	reset: function(){
	
		// start pos
		start = this.options.offset;
	
		// set initial styles
		this.children.each(function(child){
		
			// set positioning
			child
			.removeClass('selected')
			.setStyles({
				'position': 'absolute'
			});
			
			// set style
			child.setStyle(this.options.move, start);
			
			// add start position
			start += (this.options.move == 'left' ? child.getSize().x : child.getSize().y) + this.options.padding;
			
		}, this);
		
		// initial selected
		if (this.children.length > 0) this.children[0].addClass('selected');
		
		// fire event
		this.fireEvent('item', 1);
		
		// if we are offset, then we need to fill
		if (this.options.offset > 0){
		
			// pos
			var pos = this.options.offset;
			var prev = this.children[0];
			
			// loop until we are on screen
			while (pos >= 0){
			
				// old prev
				oldprev = prev;
			
				// get prev
				prev = prev.getPrevious(this.options.childType);
				if (!prev) prev = this.el.getLast(this.options.childType);
				
				// add to pos
				pos -= (this.options.move == 'left' ? oldprev.getSize().x : oldprev.getSize().y) + this.options.padding;
				
				// set style
				prev.setStyle(this.options.move, pos);
										
			}		
		
		}
	
	},
	
	// transition, feel free to change this to get different effects
	transition: function(el, from, to){
		el.tween(this.options.move, [from, to]);
	},
	
	// next
	next: function(e){

		// get selected
		var sel = this.el.getElement(this.options.childType + '.selected').removeClass('selected');
		
		// transition me to off screen
		this.transition(
			sel, 
			this.options.offset, 
			this.options.offset - (this.options.move == 'left' ? sel.getSize().x : sel.getSize().y) - this.options.padding
		);
		
		// pos
		var pos = this.options.offset;
		var opos = this.options.offset;
		var next = sel;
		
		// loop until we are off screen
		while (pos < (this.options.move == 'left' ? this.el.getSize().x : this.el.getSize().y)){
		
			// old next
			oldnext = next;
		
			// get next
			next = next.getNext(this.options.childType);
			if (!next) next = this.el.getElement(this.options.childType);
						
			if (pos == this.options.offset){
				next.addClass('selected');
		
				// fire event
				this.fireEvent('item', next.getAllPrevious(this.options.childType).length + 1);

			}
			
			// transition me on screen
			this.transition(
				next, 
				opos + (this.options.move == 'left' ? oldnext.getSize().x : oldnext.getSize().y) + this.options.padding,
				pos
			);	
			
			// add to pos
			opos += (this.options.move == 'left' ? oldnext.getSize().x : oldnext.getSize().y) + this.options.padding;
			pos += (this.options.move == 'left' ? next.getSize().x : next.getSize().y) + this.options.padding;
					
		}
		
	},
	
	// previous
	previous: function(e){

		// get selected
		var sel = this.el.getElement(this.options.childType + '.selected').removeClass('selected');
		
		// transition me to prev position
		this.transition(
			sel, 
			this.options.offset,
			this.options.offset + (this.options.move == 'left' ? sel.getSize().x : sel.getSize().y) + this.options.padding
		);
		
		// pos
		var pos = this.options.offset;
		var opos = this.options.offset;
		var prev = sel;
		
		// old prev
		oldprev = prev;
	
		// get prev
		prev = prev.getPrevious(this.options.childType);
		if (!prev) prev = this.el.getLast(this.options.childType);
		
		// i am selected
		prev.addClass('selected');
		sel = prev;
		
		// fire event
		this.fireEvent('item', prev.getAllPrevious(this.options.childType).length + 1);
		
		// loop until we are on screen
		while ((pos + (this.options.move == 'left' ? prev.getSize().x : prev.getSize().y)) >= 0){
			
			// transition me on screen
			this.transition(
				prev, 
				opos - (this.options.move == 'left' ? prev.getSize().x : prev.getSize().y) - this.options.padding,
				pos
			);	
									
			// old prev
			oldprev = prev;
		
			// get prev
			prev = prev.getPrevious(this.options.childType);
			if (!prev) prev = this.el.getLast(this.options.childType);
			
			// add to pos
			opos -= (this.options.move == 'left' ? oldprev.getSize().x : oldprev.getSize().y) + this.options.padding;
			pos -= (this.options.move == 'left' ? prev.getSize().x : prev.getSize().y) + this.options.padding;
											
		}
		
		// pos
		var pos = this.options.offset;
		var opos = this.options.offset;
		var prev = sel;
		
		// loop until we are off screen
		while (pos < (this.options.move == 'left' ? this.el.getSize().x : this.el.getSize().y)){
		
			// old prev
			oldprev = prev;
		
			// get prev
			prev = prev.getNext(this.options.childType);
			if (!prev) prev = this.el.getFirst(this.options.childType);
			
			// transition me on screen
			this.transition(
				prev, 
				pos,
				opos + (this.options.move == 'left' ? oldprev.getSize().x : oldprev.getSize().y) + this.options.padding
			);	
			
			// add to pos
			opos += (this.options.move == 'left' ? oldprev.getSize().x : oldprev.getSize().y) + this.options.padding;
			pos += (this.options.move == 'left' ? prev.getSize().x : prev.getSize().y) + this.options.padding;
					
		}
	
	}

});
