/*
    

    Author: WapplerSystems - Sven Wappler (http://www.wapplersystems.de)
    Version: 0.8

    This gallery script is based on JonDesign's SmoothGallery, but this works with prototype and scriptaculous

    Copyright (C) 2007  Sven Wappler

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA


*/

Function.prototype.create = function(options) {

	var fn = this;
	options = $H({
		'bind': fn,
		'event': false,
		'arguments': null,
		'delay': false,
		'periodical': false,
		'attempt': false
	}).merge(options);

	if (options.get('arguments') != null && typeof options.get('arguments') != 'undefined' && !(options.get('arguments') instanceof Array))
		options.set('arguments',[options.get('arguments')]);
	return function(event){
		var args = options.get('arguments') || arguments;
		if (options.get('event')){
			event = (options.get('event') === true) ? event || window.event : new options.event(event);
			args = [event].concat(args);
		}
		var returns = function(){
			return fn.apply(options.get('bind'), args);
		};
		if (options.get('delay')) return setTimeout(returns, options.get('delay'));
		if (options.get('periodical')) return setInterval(returns, options.get('periodical'));
		if (options.get('attempt')){
			try {
				var result = returns();
			} catch(err){
				result = err;
			} finally {
				return result;
			}
		} else return returns();
	}
}

Function.prototype.delay = function(ms, bind, args) {
	return this.create({'delay': ms, 'bind': bind, 'arguments': args})();
}



var Gallery = Class.create();

Gallery.prototype	= {

	initialize: function(element, options) {
		
		this.options = $H({
			showInfopane: false,
			embedLinks: false,
			fadeDuration: 0.5,
			timed: false,
			delay: 4000,
			preloader: true,
			elementSelector: "div.imageElement",
			slideInfoZoneOpacity: 0.7,
			destroyAfterPopulate: true,
			baseClass: 'swGallery',
			autostart: true
        }).merge(options);

		this.currentIter = 0;
		this.lastIter = 0;
		this.maxIter = 0;
		this.galleryElement = element;
		this.galleryData = [];
		this.galleryInit = 1;
		this.galleryElements = Array();
		this.thumbnailElements = Array();
		this.running = false;

		Element.addClassName(this.galleryElement,this.options.get('baseClass'));
		
		

		this.populateData();
		
		if (this.galleryData.length == 0) return;
		
		element.style.display = "block";
		

		this.constructElements();
		
		if ((data.length>1)) {
			/*
			var leftArrow = Builder.node('a',{className : 'left' });
			element.appendChild(leftArrow);
			Event.observe(leftArrow,'click', this.prevItem.bindAsEventListener(this), false);

			var rightArrow = Builder.node('a',{className : 'right' });
			element.appendChild(rightArrow);
			Event.observe(rightArrow,'click', this.nextItem.bindAsEventListener(this), false);
			*/
		}
		this.loadingElement = Builder.node('div',{className : 'loadingElement' });
		element.appendChild(this.loadingElement);
		
		this.initMenu();

		if (this.options.get('showInfopane')) this.initInfoSlideshow();
		this.doSlideShow(1);
	},

	populateData: function() {
		currentArrayPlace = this.galleryData.length;
		options = this.options;
		data = this.galleryData;
		
		options.get('filenames').each(function(el) {
			
			elementDict = {
				src: options.get('prefix')+el+options.get('suffix'),
				number: currentArrayPlace
			};
			
			data[currentArrayPlace] = elementDict;
			currentArrayPlace++;
		});
		
		this.galleryData = data;
	},
	constructElements: function() {
		el = this.galleryElement;
		this.maxIter = this.galleryData.length;
		var currentImg;
		for(i = 0; i < this.galleryData.length; i++) {
			var currentImg = Builder.node('div',{className : 'slideElement'});
			Element.setStyle(currentImg,{
					'position':'absolute',
					'left':'0px',
					'right':'0px',
					'margin':'0px',
					'padding':'0px',
					'backgroundImage':"url('" + this.galleryData[i].src + "')",
					'opacity':'0'
				});
			el.appendChild(currentImg);
			this.galleryElements[parseInt(i)] = currentImg;
		}
	},
	playSound : function(evt) {
		soundManager.play('mySound'+this.currentIter,this.galleryData[this.currentIter].sound);
	},
	stopSound : function(evt) {
		soundManager.stop('mySound'+this.currentIter);
	},
	goTo : function(num) {
		this.clearTimer();
		
		if (this.options.get('embedLinks'))
			this.clearLink();
		if (this.options.get('showInfopane')) {
			this.changeItem(num);
		} else
			this.changeItem.delay(500, this, num);
		if (this.options.get('embedLinks'))
			this.makeLink(num);
		
		if (this.running) this.prepareTimer();
	},
	startSlideShow : function() {
		this.loadingElement.style.display = "none";
		this.lastIter = this.maxIter - 1;
		this.currentIter = 0;
		this.galleryInit = 0;
		Element.setStyle(this.galleryElements[parseInt(this.currentIter)],{'opacity' : 100});
		if (this.options.get('showInfopane'))
			this.showInfoSlideShow.delay(1000, this);
		
		if (this.options.get('embedLinks'))
			this.makeLink(this.currentIter);
		
		if (this.options.get('autostart')) {
			this.running = true;
			this.prepareTimer();
		}
	},
	toggleSlideshow : function() {
		
		if (this.running) {
			this.running = false;
			this.clearTimer();
		} else {
			this.options.set('autostart',true);
			this.running = true;
			this.doSlideShow(this.currentIter);
			this.prepareTimer();
		}
	},
	nextItem: function() {
		this.nextIter = this.currentIter+1;
		if (this.nextIter >= this.maxIter)
			this.nextIter = 0;
		this.galleryInit = 0;
		this.goTo(this.nextIter);
	},
	prevItem: function() {
		this.nextIter = this.currentIter-1;
		if (this.nextIter <= -1)
			this.nextIter = this.maxIter - 1;
		this.galleryInit = 0;
		this.goTo(this.nextIter);
	},
	changeItem: function(num) {
		this.galleryInit = 0;
		this.thumbnailElements[this.currentIter].removeClassName("current");
		if (this.currentIter != num) {
			
			this.thumbnailElements[num].addClassName("current");
			
			for(i=0;i<this.maxIter;i++) {
				if ((i != this.currentIter)) Element.setStyle( this.galleryElements[i],{'opacity' : 0});
			}
			if (num > this.currentIter) {
				new Effect.Opacity(this.galleryElements[num], {duration: this.options.get('fadeDuration'), from:0, to: 1});
			}
			else {
				Element.setStyle( this.galleryElements[num] ,{'opacity' : 100});
				new Effect.Opacity(this.galleryElements[this.currentIter], {duration: this.options.get('fadeDuration'), from:1, to: 0});
			}
			this.currentIter = num;
		}
		this.doSlideShow.bind(this)();
	},
	clearTimer: function() {
		if (this.options.get('timed'))
			clearTimeout(this.timer);
	},
	prepareTimer: function() {
		if (this.options.get('timed'))
			this.timer = this.nextItem.delay(this.options.get('delay'), this);
	},
	doSlideShow: function(position) {
		
		if (this.galleryInit == 1) {
			imgPreloader = new Image();
			imgPreloader.onload=function(){
				this.startSlideShow();
			}.bind(this);
			imgPreloader.src = this.galleryData[0].src;
		} else {
			if (this.options.get('showInfopane')) {
				this.showInfoSlideShow.delay((500 + this.options.get('fadeDuration')), this);
			}
		}
	},
	initMenu: function () {
		this.menuContainer = $(this.options.get('menucontainerid'));

		this.constructMenuThumbnails();

	},
	thumbnailMousOver : function(e,thumbnail) {
		new Effect.Opacity(thumbnail.id, {duration:0.5, from: this.options.get('carouselMinimizedOpacity'), to:1.0});
	},
	thumbnailMousOut : function(e,thumbnail) {
		new Effect.Opacity(thumbnail.id, {duration:0.5, from: 1.0, to: this.options.get('carouselMinimizedOpacity')});
	},
	thumbnailClick : function(e,thumbnail) {

		this.goTo(thumbnail.relatedImage.number);
	},
	constructMenuThumbnails: function () {
		
		var startstopImg = Builder.node('img', { src : '/images/gallery/startstop.gif', className: 'startstop' });
		
		var startstopLink = Builder.node('a', { onclick: 'javascript: return false;', href: '#', className: 'startstopbutton' },startstopImg);
		
		this.menuContainer.appendChild(startstopLink);
		
		Event.observe(startstopLink,'click', this.toggleSlideshow.bindAsEventListener(this,startstopLink));
		
		
		for(i=0; i < this.galleryData.length; i++) {
			var currentImg = Builder.node('div', { className : 'thumbnail' , id : "thumbnail_"+i });
			
			var currentLink = Builder.node('a', { },currentImg);
			
			this.menuContainer.appendChild(currentLink);

			Event.observe(currentImg,'mouseover', this.thumbnailMousOver.bindAsEventListener(this,currentImg));
			Event.observe(currentImg,'mouseout', this.thumbnailMousOut.bindAsEventListener(this,currentImg));
			Event.observe(currentImg,'click', this.thumbnailClick.bindAsEventListener(this,currentImg));

			currentImg.relatedImage = this.galleryData[i];
			this.thumbnailElements[parseInt(i)] = currentImg;
		}
		
		for(i=0; i < 25 - this.galleryData.length; i++) {
			var currentImg = Builder.node('div', { className : 'thumbnail offline' , id : "thumbnail_"+i });
			
			this.menuContainer.appendChild(currentImg);

		}
		
		if (this.thumbnailElements[0]) this.thumbnailElements[0].addClassName("current");
	},
	initInfoSlideshow: function() {
		if (this.slideInfoZone)
			this.slideInfoZone.remove();
		this.slideInfoZone = Builder.node('div', { className : 'slideInfoZone' } );
		this.galleryElement.appendChild(this.slideInfoZone);
		var slideInfoZoneTitle = Builder.node('h2', {} );
		this.slideInfoZone.appendChild(slideInfoZoneTitle);
		var slideInfoZoneDescription = Builder.node('p', {} );
		this.slideInfoZone.appendChild(slideInfoZoneDescription);
		this.slideInfoZone.normalHeight = this.slideInfoZone.offsetHeight;
		Element.setStyle(this.slideInfoZone,{'opacity' : 0});
	},
	changeInfoSlideShow: function() {
		this.hideInfoSlideShow.delay(10, this);
		this.showInfoSlideShow.delay(500, this);
	},
	showInfoSlideShow: function() {
		element = this.slideInfoZone;
		element.getElementsBySelector('h2')[0].innerHTML = this.galleryData[this.currentIter].title;
		element.getElementsBySelector('p')[0].innerHTML = this.galleryData[this.currentIter].description;
		Effect.Appear(element,{'to' : this.options.get('slideInfoZoneOpacity')});
		return this.slideInfoZone;
	},
	hideInfoSlideShow: function() {
		this.slideInfoZone.custom({'opacity': 0, 'height': 0});
		return this.slideInfoZone;
	}
};


