if(!Nibynic) {
	var Nibynic = {}
}

Nibynic.Carousel = Class.create({
	defaultOptions: {
		items: 'li',
		container: 'ul',
		sourceUrl: false,
		startAt: 0,
		firstItemParamName: false,
		lastItemParamName: false,
		indicator: {},
		margin: 0,
		generalMargin: 0,
		moveBy: false,
		positionLeft: false
	},
	moving: false,
	minOffset: 1,
	maxOffset: -1,
	currentOffset: 0,
	forwardLoadedOffset: 0,
	backLoadedOffset: 0,
	firstItemId: false,
	lastItemId: false,
	
	initialize: function(element, options) {
		this.element = $(element);
		this.options = Object.extend(Object.extend({ }, this.defaultOptions), options || {});

		this.wrapper = this.element.down('.wrapper');
		this.container = this.element.down(this.options.container);
		this.items = this.element.select(this.options.items);
		
		this.controls = {};
		var controls = this.element.select('.control');
		controls.each(function(control) {
			if(control.hasClassName('next')) {
				control.observe('click', this.onNextClicked.bind(this));
				this.controls.next = control;
			} else if(control.hasClassName('previous')) {
				control.observe('click', this.onPreviousClicked.bind(this));
				this.controls.previous = control;
			}
		}.bind(this));
	},
	
	next: function() {
		if(this.moving || !this.canMoveForward()) {
			return false;
		}

		if(this.maxOffset < 0 && this.currentOffset == this.forwardLoadedOffset && this.options.sourceUrl) {
			this.loadMore();
		} else {		
			this.moveToNext();
		}
	},
	
	previous: function() {
		if(this.moving || !this.canMoveBack()) {
			return false;
		}
		
		if(this.minOffset > 0 && this.currentOffset == this.backLoadedOffset && this.options.sourceUrl) {
			this.loadLess();
		} else {		
			this.moveToPrevious();
		}
	},
	
	loadMore: function() {
		var parameters = { page: this.options.startAt + this.currentOffset+2 };
		
		if(this.options.lastItemParamName && this.lastItemId) {
			parameters[this.options.lastItemParamName] = this.lastItemId;
		}
		
		this.createIndicator();
		
		new Ajax.Request(this.options.sourceUrl, {
			parameters: parameters,
			method: 'get',
			onComplete: this.destroyIndicator.bind(this),
			onSuccess: this.appendContents.bind(this)
		});
	},
	
	loadLess: function() {
		var parameters = { page: this.options.startAt + this.currentOffset };
		
		if(this.options.firstItemParamName && this.firstItemId) {
			parameters[this.options.firstItemParamName] = this.firstItemId;
		}
		
		this.createIndicator();
		
		new Ajax.Request(this.options.sourceUrl, {
			parameters: parameters,
			method: 'get',
			onComplete: this.destroyIndicator.bind(this),
			onSuccess: this.prependContents.bind(this)
		});
	},
	
	appendContents: function(transport) {
		if(transport.responseText) {
			this.container.insert(transport.responseText);
			this.moveToNext();
			this.forwardLoadedOffset++;
		} else {
			this.maxOffset = this.currentOffset;
		}
	},
	
	prependContents: function(transport) {
		if(transport.responseText) {
			// new Effect.Move(this.container, {x: -1 * this.wrapper.getWidth(), duration: 0});
			// this.container.insert({ top: transport.responseText });
			this.moveToPrevious(transport.responseText);
			this.backLoadedOffset--;
		} else {
			this.minOffset = this.currentOffset;
		}
	},
	
	moveToNext: function() {
		if(this.options.positionLeft && !this.container.getStyle('left')) {
			this.container.setStyle({ left: this.container.positionedOffset().left + 'px' });
		}
		
		this.moving = true;
		new Effect.Move(this.container, {
			x: this.getMoveByForward(),
			afterFinish: function() {
				this.moving = false;
			}.bind(this)
		});
		this.currentOffset++;

		if(this.canMoveForward()) {
			this.controls.next.show();
		} else {
			this.controls.next.hide();
		}
	},
	
	moveToPrevious: function(contents) {
		if(this.options.positionLeft && !this.container.getStyle('left')) {
			this.container.setStyle({ left: this.container.positionedOffset().left + 'px' });
		}
		
		var parameters = {x: this.getMoveByBack()};
		this.moving = true;
		
		if(contents) {
			parameters['afterFinish'] = function() {
				this.container.insert({ top: contents });
				this.container.hide();
				new Effect.Move(this.container, {x: -1 * this.getMoveByBack(), duration: 0});
				this.container.appear();
				this.moving = false;
			}.bind(this);
		} else {
			parameters['afterFinish'] = function() {
				this.moving = false;
			}.bind(this);
		}
		
		new Effect.Move(this.container, parameters);
		this.currentOffset--;
		
		if(this.canMoveBack()) {
			this.controls.previous.show();
		} else {
			this.controls.previous.hide();
		}
	},
	
	canMoveForward: function() {
		return true;
		return 
			(this.maxOffset < 0 && this.container.positionedOffset().left - (this.options.margin/2) +
			 	this.container.getWidth() > this.wrapper.getWidth()) ||
			(this.currentOffset < this.maxOffset);
	},
	
	canMoveBack: function() {
		return (this.minOffset > 0 && this.container.positionedOffset().left - (this.options.margin/2) < 0) || 
			(this.currentOffset > this.minOffset);
	},
	
	getMoveBy: function(containerOffset)
	{
		containerOffset = Math.abs(containerOffset);

		if(this.options.moveBy) {
			var moveBy =  (containerOffset >= this.options.moveBy) ? 
				this.options.moveBy : containerOffset - this.options.generalMargin;
		} else {
			var moveBy = this.wrapper.getWidth()
		}
		
		return moveBy;
	},
	
	getMoveByForward: function() {
		return -1 * (this.getMoveBy(this.container.positionedOffset().left + this.container.getWidth() - this.wrapper.getWidth()) + this.options.margin);
	},
	
	getMoveByBack: function() {
		return this.getMoveBy(this.container.positionedOffset().left) + this.options.margin;
	},
	
	onNextClicked: function(event) {
		event.stop();
		this.next();
	},
	
	onPreviousClicked: function(event) {
		event.stop();
		this.previous();
	},
	
	createIndicator: function() {
		if(!this.indicator) {
			this.indicator = new Nibynic.Indicator(this.wrapper, this.options.indicator);
		}
	},
	
	destroyIndicator: function() {
		this.indicator.destroy();
		this.indicator = null;
	}
})
