var Waterfall = new Class({
	Implements: [Options, Events],
	options: {
		delay: 3000,
		duration: 500,
		sliceSize: 30,
		activeSlicePercentage: 0.50,
		imageSelector: 'img',
		startImmediately: true
	},
	
	initialize: function(imageContainer, imageList, options)
	{
		this.setOptions(options);
		this.imageList = imageList;
		this.container = $(imageContainer);
		this.image = this.container.getElement(this.options.imageSelector);
		
		this.slices = [];
		this.imageList.unshift(this.image.src);
		this.index = 0;
		this.bootstrapElements();
		
		this.__cascade = this._cascade.bind(this);
		
		if(this.options.startImmediately)
			this.start();
	},
	
	start: function()
	{
		this._running = setTimeout(this.__cascade, this.options.delay);
	},
	
	stop: function()
	{
		clearTimeout(this._running);
	},
	
	bootstrapElements: function()
	{
		
		this.container.setStyle('position', 'relative');
		var dim = this.container.getSize();

		this.sliceCount = Math.floor(dim.x / this.options.sliceSize);
		this.sliceSize  = dim.x / this.sliceCount;
		this.activeSlices = Math.ceil(this.sliceCount * this.options.activeSlicePercentage);
		
		this.container.appendChild(this.sliceContainer = new Element('div'));
		
		for(var i=0; i<this.sliceCount; i++)
		{
			var nextIndex = this.index == this.imageList.length - 1 ? 0 : this.index+1;
			var slice = new Element('div', {
				'class': 'wf_slice',
				styles : {
					width: Math.ceil(this.sliceSize) + 'px',
					height:'0%',
					position: 'absolute',
					top: '0',
					left: Math.floor(this.sliceSize * i),
					opacity: '0',
					backgroundImage: 'url("'+this.imageList[nextIndex]+'")',
					backgroundPosition: '-' + Math.floor(this.sliceSize * i) + 'px 0'
				}
			});

			this.sliceContainer.appendChild(slice);
			this.slices.push(slice);
		}
	},
	
	_cascade: function()
	{
		if(++this.index > this.imageList.length - 1) this.index = 0; 
		this.sliceContainer.setStyle('display', 'block');

		var sliceDelay = this.options.duration / this.activeSlices;
		for(var i=0; i<this.activeSlices; i++) {
			setTimeout(this._fall.bind(this, i), sliceDelay * i);			
		}
		this.fireEvent('transition', this.index);
	},
	
	_fall: function(index)
	{
		if(index == this.slices.length + this.activeSlices - 1) {
			setTimeout(this._cleanupCascade.bind(this), 100);
			this.image.set('src', this.imageList[this.index]);
			return;
		}
		if(index >= this.slices.length) return;

		var elm = this.slices[index];
		new Fx.Morph(elm, {
			unit: '%',
			duration: this.options.duration,
			onComplete: this._finishFall.bind(this, index)
		}).start({
			height: "100%",
			opacity: '1'
		});
	},
	
	_finishFall: function(index)
	{
		this._fall.call(this, index + this.activeSlices);
	},
	
	_cleanupCascade: function()
	{
		
		var nextIndex = this.index == this.imageList.length - 1 ? 0 : this.index+1;
		var i = 0;
		this.sliceContainer.setStyle('display', 'none');
		this.slices.each(function(sliceElm) { 
			sliceElm
				.setStyle('opacity', '0')
				.setStyle('height', '0%')
				.setStyle('backgroundImage', 'url("'+this.imageList[nextIndex]+'")');
		}, this);
		
		this._running = setTimeout(this.__cascade, this.options.delay);
	}
});

