var iCarousel = new Class({

	options: {

		animation: {

			type: "fadeNscroll",// fadeNscroll, scroll, fade

			direction: "left",// if type = scroll, set: top || left

			amount: 1,// if type = scroll, set the amount to scroll

			transition: Fx.Transitions.Cubic.easeInOut,

			duration: 500,

			rotate: {

				type: "manual",// auto || manual

				interval: 5000,// if type = auto, set the interval (ms)

				onMouseOver: "stop"// if type = auto, set the onmouseover behavior: stop || proceed

			}

		},



		item: {

			klass: "item",

			size: 100

		},



		idPrevious: "previous",

		idNext: "next",

		idToggle: "toggle",



		onClickPrevious: Class.empty,

		onClickNext: Class.empty,

		onPrevious: Class.empty,

		onNext: Class.empty,

		onGoTo: Class.empty

	},



	initialize: function(container, options) {

		this.setOptions(options);

		this.container = $(container);

		this.aItems = $A($$('.'+ this.options.item.klass));

		this.isMouseOver = false;



		if(this.options.idPrevious != "undefined" && $(this.options.idPrevious))

			$(this.options.idPrevious).addEvent("click", function(event) {

				new Event(event).stop();

				this._previous();

				this.fireEvent("onClickPrevious", this, 20);

			}.bind(this));// check if value is not "undefined" before start search the dom with $()

		if(this.options.idNext != "undefined" && $(this.options.idNext))

			$(this.options.idNext).addEvent("click", function(event) {

				new Event(event).stop();

				this._next();

				this.fireEvent("onClickNext", this, 20);

			}.bind(this));

		if(this.options.idToggle != "undefined" && $(this.options.idToggle))

			$(this.options.idToggle).addEvent("click", function(event) {new Event(event).stop(); this._toggle()}.bind(this));



		var oAn = this.options.animation; // short hand

		switch(this.options.animation.type.toLowerCase()) {

			case "fade":

				this.aItems.each(function(item) {

					item.fx = item.effect("opacity", {duration: oAn.duration, transition: oAn.transition});

					item.setStyle("opacity", 0);

					item.addEvents({

						"mouseenter": function() {

							this.isMouseOver = true;

							if(this.options.animation.rotate.type == "auto") this.timer = $clear(this.timer);

						}.bind(this),

						"mouseleave": function() {

							this.isMouseOver = false;

							if(this.options.animation.rotate.type == "auto") this.timer = this._autoRotate.periodical(this.options.animation.rotate.interval, this);

						}.bind(this)

					});

				}.bind(this));

				this.height = this.container.getStyle("height").toInt();

				this.atScreen = 0;

				this._animate(this.atScreen);

				break;



			default:

				(2).times(function() {

					this.aItems.each(function(item) {

						item.clone().injectInside(this.container);

					}.bind(this));

				}.bind(this));

				this.aItems = $A($$('.'+ this.options.item.klass));

				this.aItems.each(function(item) {

					item.addEvents({

						"mouseenter": function() {

							this.isMouseOver = true;

							if(this.options.animation.rotate.type == "auto") this.timer = $clear(this.timer);

						}.bind(this),

						"mouseleave": function() {

							this.isMouseOver = false;

							if(this.options.animation.rotate.type == "auto") this.timer = this._autoRotate.periodical(this.options.animation.rotate.interval, this);

						}.bind(this)

					});

				}.bind(this));

				this.fx = this.container.effects({duration: oAn.duration, transition: oAn.transition, wait: false});

				this.atScreen = this.aItems.length / 3;

				this.container.setStyle(oAn.direction, - this.atScreen * this.options.item.size);

				break;

		}



		if(this.options.animation.rotate.type == "auto") this.timer = this._autoRotate.periodical(this.options.animation.rotate.interval, this);

	},



	goTo: function(n) {

		switch(this.options.animation.type.toLowerCase()) {

			case "fade":

				var lastIndex = this.atScreen;

				this.atScreen = Math.abs(n % (this.aItems.length / 3));

				this._animate(this.atScreen, lastIndex);

				break;



			default:

				this.atScreen = Math.abs(n % (this.aItems.length / 3));

				this.atScreen += this.aItems.length / 3;

				this._animate(this.atScreen);

				break;

		}



		this.fireEvent("onGoTo", this, 20);

	},



	_previous: function() {

		switch(this.options.animation.type.toLowerCase()) {

			case "fade":

				var lastIndex = this.atScreen;

				this.atScreen -= this.options.animation.amount;

				if(this.atScreen < 0) this.atScreen = (this.aItems.length - 1);

				this._animate(this.atScreen, lastIndex);

				break;



			default:

				this.atScreen -= this.options.animation.amount;

				if(this.atScreen < this.aItems.length / 3) {

					this.container.setStyle(this.options.animation.direction, - this.options.item.size * this.aItems.length * 2 / 3);

					this.atScreen = this.aItems.length * 2 / 3 - this.options.animation.amount;

				}

				this._animate(this.atScreen);

				break;

		}



		this.fireEvent("onPrevious", this, 20);

	},



	_next: function() {

		switch(this.options.animation.type.toLowerCase()) {

			case "fade":

				var lastIndex = this.atScreen;

				this.atScreen += this.options.animation.amount;

				if(this.atScreen >= this.aItems.length) this.atScreen = 0;

				this._animate(this.atScreen, lastIndex);

				break;



			default:

				this.atScreen += this.options.animation.amount;

				if(this.atScreen > this.aItems.length * 2 / 3) {

					this.container.setStyle(this.options.animation.direction, - this.options.item.size * this.aItems.length / 3);

					this.atScreen = this.aItems.length / 3 + this.options.animation.amount;

				}

				this._animate(this.atScreen);

				break;

		}



		this.fireEvent("onNext", this, 20);

	},



	_toggle: function() {

		(this.container.getStyle("height").toInt() == 0) ?

			this.container.effect("height", { duration:1000, transition: Fx.Transitions.Sine.easeInOut }).start(this.height):

			this.container.effect("height", { duration:1000, transition: Fx.Transitions.Sine.easeInOut }).start(0);

	},



	_autoRotate: function() {

		if(this.options.animation.rotate.onMouseOver == "stop" && !this.isMouseOver) this._next();

	},



	_animate: function(a, b) {

		switch(this.options.animation.type) {

			case "fade":

				if($defined(b)) {

					this.aItems[b].fx.start(0).chain(function() {

					this.aItems[a].fx.start(1);}.bind(this));

				} else {

					this.aItems[a].fx.start(1);

				}

				break;



			case "scroll":

				var that = this;

				if(that.options.animation.direction == "top") {

					that.fx.start({"top" : - a * that.options.item.size});

				} else {

					that.fx.start({"left" : - a * that.options.item.size});

				}

				break;



			case "fadeNscroll":

				var that = this;

				if(that.options.animation.direction == "top") {

					that.fx.start({"opacity":0.90}).chain(function() {

						that.fx.start({"top" : - a * that.options.item.size}).chain(function() {

							that.fx.start({"opacity": 1});

						});

					});

				} else {

					that.fx.start({"opacity":0.90}).chain(function() {

						that.fx.start({"left" : - a * that.options.item.size}).chain(function() {

							that.fx.start({"opacity": 1});

						});

					});

				}

				break;

		}

	}

});

iCarousel.implement(new Events); // Implements addEvent(type, fn), fireEvent(type, [args], delay) and removeEvent(type, fn)

iCarousel.implement(new Options);// Implements setOptions(defaults, options)
