var _slideshows = Array();
var Slideshow = function(holder, delay, initFrom, transition, transitionSpeed, buttons) {
	this.outerHolder = holder; 
	this.transition = transition;
	this.slides = new Array();
	this.buttons = new Array();
	this.delay = delay;
	this.at = 0;
	this.transitionSpeed = transitionSpeed ? transitionSpeed : 1;
	if((typeof initFrom).toLowerCase() == 'string') {
		this.initURL = initFrom;
	} else {
		this.initURL = false;
		this.data = initFrom;
	}

	this.initiate = function() {
		if(!this.outerHolder)	alert('invalid holder for slideshow');
		addClass(this.outerHolder, 'slideshow');

		this.nav = (this.buttons.nav) ? this.buttons.nav : addChild(this.outerHolder, 'div', 'nav');
		this.innerHolder = addChild(this.outerHolder,'div', 'innerHolder');

		switch(this.transition) {
			case 'slideVert':
				break;
			case 'slideHoriz':
				this.innerHolder.style.height = this.outerHolder.offsetHeight+'px';
				break;
			case 'fade':
			default:
				this.innerHolder.style.height = this.outerHolder.offsetHeight+'px';
				break;
		}

		if(this.data) {
			if(this.initURL) {
				this.loadFromURL(this.initURL);
			} else {
				/**/
				var dat = this.data;
				for(var i in dat) {
					this.addSlide(dat[i].im, '', 'image', dat[i].title, dat[i].caption, dat[i].link, dat[i].link_title);
				}
				/**/
			}
			/**/
			if(!this.slides[0].obj.id)	this.slides[0].obj.id=0;
			/**/
		}
		this.loader = addChild(this.outerHolder, 'div');
		this.loader.style.width = '0px';
		this.loader.style.height = '0px';
		this.loader.style.overflow = 'hidden';

		var thisObj = this;
		this.keyListener = addEventHandler(window, 'keydown', function(e) {
				e = e ? e : window.event;
				if(thisObj.in_transition)	return;
				if(e.keyCode==37) { // || e.keyCode==40) {		// left / down
					thisObj.stop();
					if(thisObj.at>0)
						thisObj.getNext(false, -1);
					if(thisObj.timer) {
						clearInterval(thisObj.timer);
						thisObj.timer = false;
					}
				} else if(e.keyCode==39) { // || e.keyCode==38 || e.keyCode==32) {	// right / up / space bar
					thisObj.stop();
					thisObj.getNext();
					if(thisObj.timer) {
						clearInterval(thisObj.timer);
						thisObj.timer = false;
					}
				}
		});
		this.id = _slideshows.length;
		_slideshows[this.id] = this;
	}
	this.start = function(from) {
		this.getNext(from?from:0);

		// set initial
		var tw_in = new Tween(this.slides[this.at].obj, 'alpha', 'out.strong', 0, 1, .01);
		tw_in.start();

		if(this.timer) clearInterval(this.timer);
		if(this.slides.length>1) {
			var thisObj = this;
			this.timer = setInterval(function() { thisObj.getNext(); }, this.delay*1000);
		}
	}
	this.stop = function() {
		clearInterval(this.timer);
	}
	this.addSlide = function(img, src, type, heading, caption, link, link_title) {
		if(img==undefined)	return;
		var thisObj = this;

		var newSlide = { img:img, link:link, caption:caption };
		newSlide.obj = addChild(this.innerHolder, 'div', 'slide '+(this.slides.length?'in':'')+'active', this.slides.length);

		newSlide.imgHolder = addChild(newSlide.obj, 'div', 'imHolder');

		newSlide.img = new Image();
		newSlide.img.className = 'slideImage transparent';
		if(this.transition=='fade_in') {
			addClass(newSlide.obj, 'transparent');
			addClass(newSlide.img, 'transparent');
		}

		newSlide.img.onload = function() {
			var dims_orig = { w:this.offsetWidth, h:this.offsetHeight };
			var w0 = this.offsetWidth;
			var h0 = this.offsetHeight;
			var w1 = thisObj.innerHolder.offsetWidth;
			var h1 = thisObj.innerHolder.offsetHeight;

			var dims ={ w:w1, h:w1*h0/w0 };		// best fit width
			if(dims.h > h1) 
				dims ={ w:w0*h1/h0, h:h1 };		// best fit height

			if(thisObj.transition!='slideHoriz') 
				newSlide.img.style.marginLeft = ((w1 - dims.w)/2)+'px';
			if(thisObj.transition!='slideVert') 
				newSlide.img.style.marginTop = ((h1 - dims.h)/2)+'px';
			if(thisObj.transition=='fade') 
				fade_in(newSlide.img);

			if(!thisObj.loaded) {
				if(thisObj.onload)
					thisObj.onload();
				thisObj.loaded = true;
			}

			fade_in(newSlide.img);
		}
		var loadLayer = $('loadLayer') ? $('loadLayer') : addChild(document.body, 'div', '', 'loadLayer') ;
		loadLayer.appendChild(newSlide.img);
 		newSlide.img.src = img;

		var imHolderInner = addChild(newSlide.imgHolder, 'div', 'slideImage');
		imHolderInner.style.backgroundImage = 'url('+img+')';

		if(caption) {
			newSlide.caption = addChild(newSlide.obj, 'div', 'caption');
/*
			newSlide.caption = addChild(newSlide.obj, link ? 'a':'div', 'caption');
			if(link) {
				newSlide.caption.href = link;
				newSlide.caption.target = '_BLANK';
			}
*/
			newSlide.caption.innerHTML = (heading?'<h6>'+heading+'</h6>':heading)
							+(caption?'<div class="text">'+caption+'</div>':'')
							+(link_title?'<a href="'+link+'">'+link_title+'</a>':'');
			newSlide.caption.style.position = 'relative';
		}
		if(link) {
			// set link
			newSlide.obj.link = link;
		}

		// add overlay
		newSlide.overlay = addChild(newSlide.obj, 'div', 'overlay '+type);
		newSlide.overlay.onclick = function() {
			if(type=='video') {
				// stop current slideshow
				thisObj.stop();

				// set image to background
				if(newSlide.img) newSlide.obj.style.background = 'url('+newSlide.img.src+')';

				// remove image and overlay
				newSlide.img.style.display = 'none';
				newSlide.overlay.style.display = 'none';
				newSlide.video = createVideo(src, img, newSlide.obj.offsetWidth, newSlide.obj.offsetHeight, true, true, true);
				addClass(newSlide.video, 'video');
				newSlide.obj.appendChild(newSlide.video);
				addClass(thisObj.outerHolder, 'videoActive');
			} else {
				if(link) {
					window.open(link);
				} else if(src)	lightbox(src);
			}
		}
		newSlide.img.onclick = newSlide.overlay.onclick;
		newSlide.obj.onclick = function() { thisObj.onclick(newSlide); };
		newSlide.reset = function() {
			if(type=='video') {
				// reset video
				newSlide.overlay.style.display = 'block';
				remove(newSlide.video);
				removeClass(thisObj.outerHolder, 'videoActive');
			}
		}

		// add to quick nav
		newSlide.navNode = addChild(this.nav, 'div', (!this.slides.length?'active':''));
		newSlide.navNode.slideshow = this;
		newSlide.navNode.id = this.slides.length;
		newSlide.indx = this.slides.length;
		newSlide.navNode.onclick = function() { if(this.slideshow.timer) this.slideshow.pause(); this.slideshow.getNext(this.id); };
		/**/
		if(this.slides.length) {
			this.nav.style.display = 'block';
		} else {
			if(this.transition=='fade_in') {
				this.nav.style.display = 'none';
			}
			fade_in(newSlide.obj);
		}

		this.slides[this.slides.length] = newSlide;
		return newSlide;
	}
	this.removeSlide = function(indx) {
		var slide = this.slides[indx];
		if(slide) {
			remove(slide.obj);
			remove(slide.navNode);
			remove(slide.overlay);
			this.slides.splice(indx, 1);
		}
	}
	this.getNext = function(next, dir) {
		if(this.in_transition)	return;

		var thisObj = this; 
		if(dir==undefined)	dir = 1;

		if((next!=undefined) && (next==this.at))	this.at = -1;
		var prior = this.slides[this.at];
		
		// set where it's going to
		if(!isNaN(next))
			this.at = next;
		else if(dir>0)
			this.at++;
		else	this.at--;

		// if moved to invalid slide, moved to first if going forwards, otherwise if in reverse move to last
		if(!this.slides[this.at])
			this.at = dir<0 ? this.slides.length-1 : 0;

		if(prior) {
		       	prior.obj.className = 'slide inactive';
			prior.navNode.className = '';
			if(prior.reset)	prior.reset();
		}
		this.slides[this.at].obj.className = 'slide active';
		this.slides[this.at].navNode.className = 'active';

		this.slides[this.at].obj.style.display='block';
		if(this.transition=='fade_in') {
			addClass(this.slides[this.at].obj, 'transparent');
		}

		var tw_in, tw_out;
		if(prior && prior.obj) {
			this.in_transition = true;
		}
		switch(this.transition) {
			case 'slideVert':
				break;
			case 'slideHoriz':
				var obj = this.slides[this.at].obj;
				var siblings = obj.parentNode.childNodes;
				var start = 0;
				for(var i=0; i<siblings.length && siblings[i]!=obj; i++) {
					start += siblings[i].offsetWidth;
				}
				if(dir && dir < 0) {		// move right
					// move last to first place and displace animation
					var slideObjs = this.innerHolder.childNodes;
					var w = slideObjs[slideObjs.length-1].offsetWidth;
					var last = remove(slideObjs[slideObjs.length-1]);
					this.innerHolder.style.marginLeft = (w*-1)+'px';
					this.innerHolder.insertBefore(last, this.innerHolder.firstChild);
					tw_move = new Tween(this.innerHolder, 'marginLeft', 'out.normal', w*-1, 0, this.transitionSpeed);
					tw_move.onstop = function() {
						thisObj.in_transition = false;
					}
				} else {
					tw_move = new Tween(this.innerHolder, 'marginLeft', 'out.normal', 0, start*-1, this.transitionSpeed);
					// move to end
					tw_move.onstop = function() {
						thisObj.innerHolder.style.marginLeft = '0px';
						if(prior && prior.obj) 
							thisObj.innerHolder.appendChild(prior.obj);
						thisObj.in_transition = false;
					}
				}
				if(tw_move) 	tw_move.start();
				break;
			case 'fade':
			default:
				tw_in = new Tween(this.slides[this.at].obj, 'alpha', 'out.strong', 0, 1, this.transitionSpeed, 40);
				if(prior && prior.obj) {
					tw_out = new Tween(prior.obj, 'alpha', 'out.strong', 1, 0, this.transitionSpeed, 40);
					tw_out.onstop = function() { 
						thisObj.in_transition = false;
					}
				}
				if(tw_in) tw_in.start();
				if(prior && prior.obj && tw_out) 	tw_out.start();
				break;
		}
		if(this.slides[this.at].onselect) 	this.slides[this.at].onselect();
		if(prior && prior.unselect) 		prior.onunselect(); 
	}
	this.getSlide = function(indx) {
		if(!indx)	indx=0;
		return this.slides[indx] ? this.slides[indx].obj : false;
	}
	this.goTo = function(slide) {
		this.getNext(slide);
	}
	this.pause = function() {
		this.paused = true;
		if(this.timer) {
			clearInterval(this.timer);
			this.timer = false;
		}
	}
	this.resume = function() {
		this.paused = false;
		if(this.timer) {
			clearInterval(this.timer);
		}
		if(this.slides.length>1)	
			this.timer = setInterval('_slideshows['+this.id+'].getNext()', this.delay*1000);
	}
	this.loadFromURL = function(url) {
		var data = load(url);
		var slide = '';
		while(slide=parseXML(data, 'slide')) {
			this.addSlide(
					parseXML(slide,'im'),
					parseXML(slide,'ttl'),
					parseXML(slide,'capt'),
					parseXML(slide,'a_url'),
					parseXML(slide,'a_ui')
				     );
			data = eatXML(data, 'slide');
		}
	}

	this.initiate();
}

