var Fader = Class.create(
	{
		animating: false,
		previousSlideIndex: false,
		currentSlideIndex: 0,
		console: {
			info: function (message)
			{
				alert(message);
			},
			warn: function (message)
			{
				alert(message);
			},
			error: function (message)
			{
				alert(message);
			},
			debug: function (message)
			{
				alert(message);
			}
		},

		initialize: function (container, options)
		{
			if(typeof console !== "undefined" && console !== null)
			{
				this.console = console;
			}

			this.container = $(container);
			this.options = Object.extend(
				{
					slidesContainer: ".slides",
					autoRotateTimeout: 5,
					positionIndicators: false
				},
				options || {}
			);

			/* Set up the position indicators, automatically add the "active" classname to the first one */
			this.positionIndicators = false;
			if(this.options.positionIndicators)
			{
				this.positionIndicators = $(this.container.down(this.options.positionIndicators)) || false;

				if(this.positionIndicators)
				{
					this.positionedItemHash = $H({});
					this.positionIndicators.childElements().each(
						function (elem, i)
						{
							this.positionedItemHash.set(elem.identify(), i);
							elem.observe("click", this.moveToPosition.bind(this));
						}.bind(this)
					);

					this.positionIndicators.firstDescendant().addClassName("active");
				}
				else
				{
					console.error(
						"Position indicators selector not found.  Was looking for \"" + 
						this.container.inspect() + " " + this.options.positionIndicators + 
						"\".  They will be disabled."
					);
				}
			}

			this.animOptions = Object.extend(
				{
					duration: 0.75,

					beforeStartCallback: function () {},
					afterFinishCallback: function () {}
				},
				this.options.animOptions || {}
			);

			this.animOptions.beforeStart = function (effect)
			{
				this.animating = true;

				this.animOptions.beforeStartCallback(effect);

				if(this.positionIndicators)
				{	
					this.positionIndicators.childElements()[this.currentSlideIndex].removeClassName('active');
				}
			}.bind(this);

			this.animOptions.afterUpdate = function (effect)
			{
				if(
					this.positionIndicators && 
					(typeof effect.options.positionIndicatorFaded === "undefined" || !effect.options.positionIndicatorFaded) && 
					effect.currentFrame >= (effect.totalFrames * 0.5) // Greather than 50%
				)
				{
					effect.options.positionIndicatorFaded = true;

					this.positionIndicators.childElements()[effect.options.nextSlideIndex].addClassName("active");
				}
			}.bind(this);

			this.animOptions.afterFinish = function (effect)
			{
				this.animOptions.afterFinishCallback(effect);

				this.slides[this.currentSlideIndex].setStyle(
					{
						zIndex: 1,
						opacity: 0
					}
				);

				this.currentSlideIndex = effect.options.nextSlideIndex;

				this.slides[this.currentSlideIndex].setStyle(
					{
						zIndex: 2
					}
				);

				this.animating = false;
			}.bind(this);

			this.slidesContainer = this.container.down(this.options.slidesContainer);
			this.slides = this.slidesContainer.childElements();

			this.slides.each(
				function (slide)
				{
					var zIndex = 1;
					if($(slide) == this.slidesContainer.firstDescendant())
					{
						zIndex = 2;
					}

					slide.setStyle(
						{
							zIndex: zIndex
						}
					);
				}.bind(this)
			);

			this.pe = new PeriodicalExecuter(this.autoFade.bind(this), parseInt(this.options.autoRotateTimeout) || 5);
		},

		autoFade: function (pe)
		{
			this.fadeToSlide(this.currentSlideIndex + 1);
		},

		fadeToSlide: function (nextSlideIndex)
		{
			// Don't interrupt previous fades
			if(this.animating)
			{
				return;
			}

			if(nextSlideIndex < 0)
			{
				nextSlideIndex = this.slides.size();
			}

			if(nextSlideIndex >= this.slides.size())
			{
				nextSlideIndex = 0;
			}

			var currentSlide = this.slides[this.currentSlideIndex];
			var nextSlide = this.slides[nextSlideIndex];

			nextSlide.setStyle(
				{
					opacity: 0
				}
			);

			nextSlide.setStyle(
				{
					zIndex: 5
				}
			);

			this.animOptions.from = 0;
			this.animOptions.to = 1;
			this.animOptions.nextSlideIndex = nextSlideIndex;

			nextSlide.fade(this.animOptions);
		},
		
		moveToPosition: function (e)
		{
			Event.stop(e);

			if(typeof this.pe !== "undefined" && this.pe !== null)
			{
				this.pe.stop();
				this.pe = null;
			}

			this.fadeToSlide(this.positionedItemHash.get(Event.findElement(e).identify()));
		}
	}
);
