/**
* moogal.js: class for applying a series of fade-in effects to an
* arbitrary number of (image) elements.  The fade-ins are independent 
* of one another.  Individual delays control the start of each effect.
* For example, one effect can begin before the preceeding effect has
* completed.
*
* Dependencies: Mootools 1.2.2 core.
*
* Class name: MooGal
* Version: 1.0
* License: MIT-style license
* Copyright: Richard Manning 2009
*
* Author: Richard Manning
* Author URL: http://richardimanning.com/
*
*
*/

var MooGal = new Class({
	Implements: [Chain, Options],
	
	options: {
		duration: 3000,
		delay: 400,
		transition: Fx.Transitions.Sine.easeInOut
	},
	
	initialize: function(gallery, options){
		this.gallery = $$(gallery).length == 0 ? $$('.' + gallery) : $$(gallery);
		if (!this.gallery.length) return;
		this.setOptions(options);
		this.timerArray = [];
		this.gallerySort();
		this.galleryFx();
		this.load();
	},
	
/**
Randomizes the order of the elements in the gallery array. The randomization
is performed 3 times because the "pseudo-random" numbers produced by Math.random()
aren't particularly random.
*/
	gallerySort: function(){
		for (i = 0; i < 3; i++) {
			this.gallery = this.gallery.sort(function() {return 0.5 - Math.random()});
		}
	},
	
/**
Creates a tween instance for each element and stores it in the element.
*/
	galleryFx: function(){
		this.gallery.each(function(picture){
			picture.store('fx', new Fx.Tween(picture, {property:'opacity', duration:this.options.duration, link:'cancel', transition:this.options.transition}));
		}, this);
		return this.gallery;
	},
	
/**
Retrieves tween instances and places them on the call stack.
*/
	load: function(){
		this.clearChain(); // clear the call stack of any remaining tween instances.
		this.gallery.each(function(picture){
			this.chain(
				function() {picture.retrieve('fx').set(0).start(1);}
			);
		}, this);
	},
	
/**
Cancels or pauses the transitions.  This method takes a boolean argument.
If cancelled = true, the effect is completely cancelled; if false, the
effect is simply paused.
*/
	cancel: function(cancelled){
		if (cancelled){
			this.clearChain();
			this.gallery.each(function(picture){
				picture.retrieve('fx').cancel().set(0);
			});
		}
		// clear the timers to prevent any more transitions from starting.
		for (i = 0; i < this.timerArray.length; i++){
			$clear(this.timerArray[i]);
		}
		this.timerArray.empty(); // empty the timer id array.
	},
	
/**
Runs the transitions by removing tween instances from the call stack
and executing them with delays.
*/
	run: function() {
		var i = 0;
		// $chain is an internal Mootools array that holds the chained functions.
		var chainLength = this.$chain.length;
		while (i < chainLength) {
			// set up delays and start running the transitions one after another.
			// binding is tricky here.
			// with a default delay of 400ms, the first effect starts at t=0, the second at t=0.4sec,
			// the third at t=0.8sec, the fourth at t=1.2sec, etc.
			this.timer = (function() {this.callChain();}.bind(this)).delay(i * this.options.delay);
			this.timerArray[i] = this.timer; // store timer ids in a timer array.
			i++;
		}
		return this;
	}

});
