/*
Script: Slideshow.js
	Slideshow - A javascript class for Mootools to stream and animate the presentation of images on your website.

License:
	MIT-style license.

Copyright:
	Copyright (c) 2008 [Aeron Glemann](http://www.electricprism.com/aeron/).
	
Dependencies:
	Assets, Fx.Morph, Fx.Tween, Selectors, Element.Dimensions.
*/

Slideshow = new Class({
	Implements: [Chain, Events, Options],
	
	options: {
		captions: false,
		center: true,
		classes: [],
		controller: false,
		delay: 2000,
		duration: 750,
		fast: false,
		height: false,
		href: '',
		hu: '/',
		linked: false,
		loader: {'animate': ['css/loader-#.png', 12]},
		loop: true,
		match: /\?slide=(\d+)$/,
		overlap: true,
		paused: false,
		quick: false,
		random: false,
		replace: [/\.(.{3})$/, 't.$1'],
		resize: true,
		slide: 0,
		thumbnails: false,
		transition: function(p){return -(Math.cos(Math.PI * p) - 1) / 2;},
		width: false
	},
	
	// constructor

	initialize: function(el, data, options){	
		this.setOptions(options);
		this.slideshow = $(el);
		if (!this.slideshow) 
			return;
		this.slideshow.set('styles', {'display': 'block', 'position': 'relative'});
		var keys = ['slideshow', 'first', 'prev', 'play', 'pause', 'next', 'last', 'images', 'captions', 'controller', 'thumbnails', 'hidden', 'visible', 'inactive', 'active', 'loader'];
		var values = keys.map(function(key, i){
			return this.options.classes[i] || key;
		}, this);
		this.classes = values.associate(keys);
		this.classes.get = function(){
			var str = '.' + this.slideshow;
			for (var i = 0, l = arguments.length; i < l; i++)
				str += ('-' + this[arguments[i]]);
			return str;
		}.bind(this.classes)
		var anchor = this.slideshow.getElement('a') || new Element('a');
		if (!this.options.href)
			this.options.href = anchor.get('href') || '';
		if (this.options.hu.substr(-1) != '/') 
			this.options.hu += '/';
		if (!data){
			data = {};
			this.slideshow.getElements(this.classes.get('images') + ' img').each(function(img){
				var el = img.getParent();
				var href = el.get('href') || '';
				var src = img.get('src').split('/').getLast();
				data[src] = {caption: img.get('alt'), href: href};
			});
		}
		this.load(data);
		if (!this.data.images.length)
			return; 
		var match = window.location.href.match(this.options.match);
		this.counter = 0;
		this.slide = (this.options.match && match) ? match[1] % this.data.images.length : this.options.slide;
		this.paused = this.stopped = false;
		if (!this.options.overlap)
			this.options.duration *= 2;
		var el = this.slideshow.getElement('img');
		this.a = this.image = (el) ? el : new Element('img');
		this.a.set({
			'src': this.options.hu + this.data.images[this.slide],
			'styles': {'display': 'block', 'position': 'absolute', 'zIndex': 1}
		});
		var image = this.a.getSize();
		this.width = (this.options.width || image.x);
		this.height = (this.options.height || image.y);		
		if (this.options.width || this.options.height)		
			this._resize(this.a, image.x, image.y);
		var el = this.slideshow.getElement(this.classes.get('images'));
		var images = (el) ? el.empty() : new Element('div', {'class': this.classes.get('images').substr(1)}).inject(this.slideshow);
		images.set({'styles': {'display': 'block', 'height': this.height, 'overflow': 'hidden', 'position': 'relative', 'width': this.width}});
		this.slideshow.store('images', images);
		if (this.data.hrefs[this.slide])
			anchor.set('href', this.data.hrefs[this.slide]);		
		anchor.clone().grab(this.a).inject(images);
		this.b = this.a.clone().setStyle('visibility', 'hidden');
		anchor.clone().grab(this.b).inject(images);
		this.events = $H({'keydown': [], 'keyup': [], 'mousemove': []});
		if (this.options.loader)
 			this.loader();
		if (this.options.captions)
 			this.captions();
		if (this.options.controller)
			this.controller();
		if (this.options.thumbnails)
			this.thumbnails();
		var keyup = function(e){
			switch(e.key){
				case 'left': 
					this.prev(e.shift); break;
				case 'right': 
					this.next(e.shift); break;
				case 'space': 
					this.pause(); break;
			}
		}.bind(this);		
		this.events.keyup.push(keyup);
		document.addEvent('keyup', keyup);
		if (this.options.paused)
			this.pause();
		if (this.data.images.length > 1)
			this.loaded(this.options.quick);
	},
	
	// loads data

	load: function(data){
		this.showed = {'array': [], 'i': 0};
		if ($type(data) == 'array'){
			this.options.captions = false;			
			data = new Array(data.length).associate(data); 
		}
		this.data = {'images': [], 'captions': [], 'hrefs': [], 'thumbnails': []};
		for (image in data){
			var obj = data[image] || {};
			var caption = (obj.caption) ? obj.caption.trim() : '';
			var href = (obj.href) ? obj.href.trim() : ((this.options.linked) ? this.options.hu + image : this.options.href);
			var thumbnail = (obj.thumbnail) ? obj.thumbnail.trim() : image.replace(this.options.replace[0], this.options.replace[1]);
			this.data.images.push(image);
			this.data.captions.push(caption);
			this.data.hrefs.push(href);
			this.data.thumbnails.push(thumbnail);
		}
		if (this.options.thumbnails && this.slideshow.retrieve('thumbnails'))
			this.thumbnails();
		if (this.slideshow.retrieve('images')){
			[this.a, this.b].each(function(img){
				['morph', 'tween'].each(function(p){
					if (this.retrieve(p)) this.get(p).cancel();
				}, img);
			});
			this.slide = this.transition = 0;
			this.go(0);		
		}
		return this.data.images.length;
	},
	
	// preloads the next slide in the show, once loaded triggers the show, updates captions, thumbnails, etc

	preload: function(fast){
		if (this.preloader.complete && $time() > this.delay && $time() > this.transition){
			if (this.stopped){
				if (this.options.captions)
					this.slideshow.retrieve('captions').get('morph').cancel().start(this.classes.get('captions', 'hidden'));
				this.pause(1);
				return;				
			}					
			this.image = (this.counter % 2) ? this.b : this.a;
			this.image.set({
				'src': this.preloader.get('src'),
				'styles': {'height': 'auto', 'visibility': 'hidden', 'width': 'auto', 'zIndex': this.counter}
			});	
			this._resize(this.image, this.preloader.width, this.preloader.height);
			var anchor = this.image.getParent();
			if (this.data.hrefs[this.slide])
				anchor.set('href', this.data.hrefs[this.slide]);			
			else
				anchor.erase('href');	
			if (this.options.loader)
				this.slideshow.retrieve('loader').fireEvent('hide');
			if (this.options.captions)
				this.slideshow.retrieve('captions').fireEvent('update', fast);				
			if (this.options.thumbnails)
				this.slideshow.retrieve('thumbnails').fireEvent('update', fast); 			
			this.show(fast);
			this.loaded();
		} 
		else {
			if ($time() > this.delay && this.options.loader)
				this.slideshow.retrieve('loader').fireEvent('show');
			this.timer = (this.paused) ? null : this.preload.delay(100, this, fast); 
		}
	},

	// does the slideshow effect

	show: function(fast){
		if (!this.image.retrieve('morph')){
			var options = (this.options.overlap) ? {'duration': this.options.duration, 'link': 'cancel'} : {'duration': this.options.duration / 2, 'link': 'chain'};
			$$(this.a, this.b).set('morph', $merge(options, {'transition': this.options.transition}));
		}
		this._center(this.image);
		var hidden = this.classes.get('images', ((this.direction == 'left') ? 'next' : 'prev'));
		var visible = this.classes.get('images', 'visible');
		if (fast)
			this.image.get('morph').cancel().set(visible); 			
		else {
			var img = (this.counter % 2) ? this.a : this.b;
			if (this.options.overlap){	
				img.get('morph').set(visible);
				this.image.get('morph').set(hidden).start(visible);
			} 
			else	{
				var fn = function(hidden, visible){
					this.image.get('morph').set(hidden).start(visible);
				}.pass([hidden, visible], this);
				var hidden = this.classes.get('images', ((this.direction == 'left') ? 'prev' : 'next'));
				img.get('morph').set(visible).start(hidden).chain(fn);
			}
		}
	},
	
	// run after the current image has been loaded, sets up the next image to be shown

	loaded: function(quick){
		this.counter++;
		if (this.paused){
			this.delay = Number.MAX_VALUE;
			this.transition = 0;			
		}
		else {
			this.delay = (quick) ? 0 : $time() + this.options.duration + this.options.delay;
			this.transition = (quick || this.options.fast) ? 0 : $time() + this.options.duration;			
		}
		this.direction = 'left';
		if (this.slide + 1 == this.data.images.length && !this.options.loop && !this.options.random)
			this.stopped = true;
		if (this.options.random){
			this.showed.i++;
			if (this.showed.i >= this.showed.array.length){
				var n = this.slide;
				if (this.showed.array.getLast() != n) this.showed.array.push(n);
				while (this.slide == n)
					this.slide = $random(0, this.data.images.length - 1);				
			}
			else
				this.slide = this.showed.array[this.showed.i];
		}
		else
			this.slide = (this.slide + 1) % this.data.images.length;
		if (this.preloader) this.preloader.destroy();
		this.preloader = new Asset.image(this.options.hu + this.data.images[this.slide]);		
		this.preload();
	},

	// toggle whether the slideshow is paused or not

	pause: function(p){
		if ($chk(p))
			this.paused = (p) ? false : true;
		if (this.paused){
			this.paused = this.stopped = false;
			this.delay = this.transition = 0;		
			this.timer = this.preload.delay(100, this);
			[this.a, this.b].each(function(img){
				['morph', 'tween'].each(function(p){
					if (this.retrieve(p)) this.get(p).resume();
				}, img);
			});
			if (this.options.controller)
				this.slideshow.getElement('.' + this.classes.pause).removeClass(this.classes.play);
		} 
		else {
			this.paused = true;
			this.delay = Number.MAX_VALUE;
			this.transition = 0;
			$clear(this.timer);
			[this.a, this.b].each(function(img){
				['morph', 'tween'].each(function(p){
					if (this.retrieve(p)) this.get(p).pause();
				}, img);
			});
			if (this.options.controller)
				this.slideshow.getElement('.' + this.classes.pause).addClass(this.classes.play);
		}
	},

	// builds the optional streaming loader

	loader: function(){
 		if (this.options.loader === true) 
 			this.options.loader = {};
		var loader = new Element('div', {
			'class': this.classes.get('loader').substr(1),				
			'morph': $merge(this.options.loader, {'link': 'cancel'})
		}).store('hidden', false).store('i', 1).inject(this.slideshow.retrieve('images'));
		if (this.options.loader.animate){
			for (var i = 0; i < this.options.loader.animate[1]; i++)
				img = new Asset.image(this.options.loader.animate[0].replace(/#/, i));
			if (Browser.trident4 && this.options.loader.animate[0].contains('png'))
				loader.setStyle('backgroundImage', 'none');					
		}
		loader.set('events', {
			'animate': function(){  
				var loader = this.slideshow.retrieve('loader');				
				var i = (loader.retrieve('i').toInt() + 1) % this.options.loader.animate[1];
				loader.store('i', i);
				var img = this.options.loader.animate[0].replace(/#/, i);
				if (Browser.trident4 && this.options.loader.animate[0].contains('png'))
					loader.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + img + '", sizingMethod="scale")';
				else 
					loader.setStyle('backgroundImage', 'url(' + img + ')');
			}.bind(this),
			'hide': function(){  
				var loader = this.slideshow.retrieve('loader');
				if (!loader.retrieve('hidden')){
					loader.store('hidden', true).morph(this.classes.get('loader', 'hidden'));
					if (this.options.loader.animate)
						$clear(loader.retrieve('timer'));					
				}
			}.bind(this),
			'show': function(){  
				var loader = this.slideshow.retrieve('loader');
				if (loader.retrieve('hidden')){
					loader.store('hidden', false).morph(this.classes.get('loader', 'visible'));
					if (this.options.loader.animate)
						loader.store('timer', function(){this.fireEvent('animate');}.periodical(50, loader));
				}
			}.bind(this)
		});
		this.slideshow.retrieve('loader', loader).fireEvent('hide');
	},
	
	// destroy a slideshow instance, remove document events, clear callbacks, clear fx

	destroy: function(p){
		this.events.each(function(array, e){
			array.each(function(fn){ document.removeEvent(e, fn); });
		});
		this.pause(1);
		if (this.options.loader)
			$clear(this.slideshow.retrieve('loader').retrieve('timer'));		
		if (this.options.thumbnails)
			$clear(this.slideshow.retrieve('thumbnails').retrieve('timer'));
		Element.Storage[this.slideshow.uid] = {};
		if (p)
			$try(this.slideshow[p]());
	},
	
	// helper function to center an image

	_center: function(img){
		if (this.options.center){
			var size = img.getSize();
			img.set('styles', {left: (size.x - this.width) / -2, top: (size.y - this.height) / -2});
		}
	},

	// helper function to resize an image

	_resize: function(img, w, h){
		if (this.options.resize){
			var dh = this.height / h;
			var dw = this.width / w;
			var delta = (dw > dh) ? dw : dh;
			img.set('styles', {height: Math.ceil(h * delta), width: Math.ceil(w * delta)});
		}	
	}
});

var img = [];
var dsSl= null;
var objSl = [];
var idSl = 0;

function ReadSlideData(sl)
{
  dsSl = new Spry.Data.XMLDataSet("../data/slideshow.xml", "/slideshows/slideshow",	{ subPaths: "images/image" });
  dsSl.loadData();
  
  var obj = new Object;
  obj.onPostLoad = function(ds, type) {
    if(dsSl.getDataWasLoaded()){
      dsSl.removeObserver(obj); 
	  	AddSlideShow(sl);
    }
  }
  dsSl.addObserver(obj);
}

function AddSlideShow(sl)
{
	SlideShowStopAll();
	if (SlideShowExist(sl))
	{
		SlideShowRun(sl);
  	return;
	}
	// Create slide show object
	objSl[idSl] = new Object;
	// initialize object
 	objSl[idSl].name = 'sl'+ sl;
 	objSl[idSl].img  = [];
 	objSl[idSl].show = null;
	GetImageList(objSl[idSl]);
	
	objSl[idSl].show = new Slideshow(objSl[idSl].name, objSl[idSl].img, { captions: false, controller: false, duration: 3000, delay: 1000,  transition:Fx.Transitions.Cubic.easeInOut, hu: '../images/products/' });
  idSl++;
}

function GetImageList(obj)
{
  var rows=null;
	var i=0;
	var j=0;
	
  rows= dsSl.getData();	
  for (i = 0; i < rows.length; i++)
	{
	  if(rows[i]['name']==obj.name)
	  {
	    obj.img[j++] = rows[i]['images/image'];
	  }
  }
}

function SlideShowStopAll()
{
  // myShow.pause(p); Arguments:  1. p - (undefined, 1 or 0) Call pause with no arguments to toggle the pause state. Call pause(1) to force pause, or pause(0) to force play. 	
	for (var i=0;i<objSl.length;i++) {
		objSl[i].show.pause(1);
	}
}

function SlideShowRun(sl)
{
	for (var i=0;i<objSl.length;i++) {
	  if (objSl[i].name == 'sl'+ sl)
		{
			objSl[i].show.pause(0);
			break;
		}
	}
}

function SlideShowExist(sl)
{
	var bRun = false;
	for (var i=0;i<objSl.length;i++) {
	  if (objSl[i].name == 'sl'+ sl)
		{
			bRun = true;
			break;
		}
	}
	return bRun;
}

function StartSlideShow(sl)
{
	if (dsSl == null)
    ReadSlideData(sl);
	else
	{
    if(dsSl.getDataWasLoaded())		
	    AddSlideShow(sl);
	}
}

function InitSlideShow()
{
  // Evaluate URL params
  var params = Spry.Utils.getLocationParamsAsObject();
		
	if (dsSl == null)
    ReadSlideData(params.sl);
	else
	  AddSlideShow(params.sl);
}

Spry.Utils.addLoadListener(InitSlideShow);
