/*
 *
 *
 */
var Slideshow = Class.create();

Slideshow.prototype = {
	
	initialize : function (holders, images, options) {
		
		this.holders     = $A(holders).map( function (e) { return $(e) });
		this.images      = $A(images);
		this.updateProgress = options.onprogress || false;
		this.callback    = options.onload   || false;
		this.width       = options.width    || 0;
		this.interval    = options.interval || 5;
		this.duration    = options.duration || 1; 
		this.running     = false;
		this.preloaded   = false;    
		
		this.progress    = 1;
		
		this.imagesCache   = [];
		
		this.onImageLoaded = this.imageLoaded.bindAsEventListener(this);
		this.doMove        = this._move.bind(this);
		
		var img            = document.createElement('img');
		img.alt            = '';
		img.style.position = 'absolute';
		img.style.top      = '0px';
		img.style.left     = '0px';
		img.src            = this.images[0];
		
		this.imagesCache.push(img.cloneNode(false));
		
		Event.observe(this.imagesCache[0], 'load', this.onImageLoaded);
		
		this.BACK        = 1;
		this.FORWARD     = -1;
		this.STOP        = 0;
		
		this.range_start = 0;
		this.range_end   = this.images.length - 1;
		
		this.direction   = this.FORWARD; // from right to left (1 - from left to right)
		this.current     = 0;
		
		this.holders[0].appendChild(this.imagesCache[0].cloneNode(false));
		this.holders[1].appendChild(this.imagesCache[0].cloneNode(false));
		
		Event.observe(window, 'load', this.load.bind(this));
	},
	
	load : function () {
		
		for (var i = 1; i < this.images.length; i++)
		{
			var img            = document.createElement('img');
			img.alt            = '';
			img.style.position = 'absolute';
			img.style.top      = '0px';
			img.style.left     = '0px';
			img.src            = this.images[i];
			
			this.imagesCache.push(img);

			Event.observe(this.imagesCache[this.imagesCache.length - 1], 'load', this.onImageLoaded);
			
			this.holders[0].appendChild(img.cloneNode(false))
				.style.left = i * (-1) * this.width + 'px';

			this.holders[1].appendChild(img.cloneNode(false))
				.style.left = i * this.width + 'px';
		}
		
		this.preloaded = true;

		this.updateProgress && this.updateProgress(this.progress / this.images.length);
	},
	
	_appendImage : function ()
	{
		this.holders[0].appendChild(this.imagesCache[0].cloneNode(false))
			.style.left = this.current * -1 * this.width + 'px';;

		this.holders[1].appendChild(this.imagesCache[0].cloneNode(false))
			.style.left = this.current * this.width + 'px';
		
		this.direction == this.FORWARD ? this.range_end++ : this.range_start--;
	},
	
	imageLoaded : function ()
	{
		//this.downCounter--;
		this.progress++;
		this.updateProgress && this.updateProgress(this.progress / this.images.length);
		
		if (this.preloaded && this.progress == this.images.length)
		{
			for (var i = 0; i < this.imagesCache.length; i++)
			{
				Event.stopObserving(this.imagesCache[i], 'load', this.onImageLoaded);
			}
			this.callback && this.callback();
			this.run(this.direction, true);
		}
	},
	
	run : function (direction, delayed)
	{
		this.pe && this.pe.stop();		
		this.direction = direction;
		if (!delayed && !this.running) this.doMove();
		this.pe = new PeriodicalExecuter(this.doMove, this.interval);
	},
	
	_move : function (pe) {
		
		if (!this.running)
		{
			this.running = true;
			this.current += this.direction * -1;
		
			this.direction == this.FORWARD 
				? this.imagesCache.push(this.imagesCache.shift())
				: this.imagesCache.unshift(this.imagesCache.pop());
			
			!$R(this.range_start, this.range_end).include(this.current) && this._appendImage();
			
			new Effect.Parallel([
				new Effect.Move(this.holders[0],  {
								x    : this.width * this.direction * -1, 
								y    : 0, 
								mode : 'relative',
								sync : true,
								fps  : 20
				}),
				new Effect.Move(this.holders[1],  {
								x    : this.width * this.direction, 
								y    : 0, 
								mode : 'relative',
								sync : true,
								fps  : 20
				})
			], {duration : this.duration, afterFinish : function () { this.running = false }.bind(this) });
		}
		
	},
	
	stop : function ()
	{
		this.pe && this.pe.stop();
	}
}