// VARIABLES________________________________________________________________________________

var elSlideshow = fnGet('slideshow'); // which element is the slideshow container
var elSlidePrevious = fnGet('slide'); // find the first image in the slideshow container
var inShowDuration = 3000; // millseconds (editable)
var inFadeDuration = 1500; // millseconds (editable)
var inFps = 30; // frames per second (editable)
var inStepTime = 1000 / inFps; // time between steps
var inIncrement = 1000 / (inFps * inFadeDuration); // size of each step
var boFadeActive = false; // fade not currently running
var t = null; // timeouts

// Create an array with links and captions dervived from page navigation AND add onclicks
if (boSlideGallery) {
	var inSlideNext = 0; // which image in list to start from
	var arImageLinks = fnGet('gallery').getElementsByTagName('a'); // get all image links
	var arImageData = new Array();
	for (i=0, j=arImageLinks.length; i<j; i++) {
		arImageLinks[i].onclick = fnSlideshowGalleryThumb;
		arImageData.push([arImageLinks[i].href,arImageLinks[i].getElementsByTagName('img')[0].alt]); // build link and alt tag data
	}
}

// only enable slideshow if more than 1 image AND a slideshow container AND first slide exists
if (elSlideshow && elSlidePrevious && arImageData.length > 1) {var boSlideshow = true;}



// LAUNCHER_________________________________________________________________________________

if (boSlideshow) {
	fnPrepare(); // add the next slide to the page
	if (boSlideshowPlay) {
		if (boSlideGallery) {
			fnClassSwap(elControls, 'pause', 'play');
		}
		clearTimeout(t);
		t = setTimeout(function() { // start off by fading in first slide after standard delay
			if (boSlideshowPlay) {
				fnSlideTransition(1);
			}
		}, inShowDuration);
	}
}



// FUNCTIONS________________________________________________________________________________

// add a transition slide to the slideshow
function fnPrepare() {
	elSlidePrevious.src = arImageData[inSlideNext][0]; // start with chosen slide
	elSlideNext = document.createElement('img');
	elSlideNext.id = 'slideNext';
	fnSetOpacity(elSlideNext,0);
	insertAfter(elSlidePrevious,elSlideNext);
	if (boSlideGallery) { // add a caption to the slideshow
		elCaption = document.createElement('p');
		elCaptionText = document.createTextNode(arImageData[inSlideNext][1]);
		elCaption.appendChild(elCaptionText);
		elSlideshow.appendChild(elCaption);
		elControls = document.createElement('div'); // add player controls
		elControls.className = 'pause';
		elControls.id = 'slideshowControls';
		elSlideshow.appendChild(elControls);
		elControls.innerHTML = '<a onclick="fnSlideshowControlPlay();" class="play">play</a><a onclick="fnSlideshowControlPause();" class="pause">pause</a><a onclick="fnSlideshowControlPrevious();" class="previous">previous</a><a onclick="fnSlideshowControlNext();" class="next">next</a>';
	}
}

// launch a fade in starting at a set opacity
function fnSlideTransition(increment) {
	if (!boFadeActive) {
		inSlideNext = fnNewItem(arImageData,inSlideNext,increment); // choose next slide to show
		elSlideNext.src = arImageData[inSlideNext][0]; // put it in container
		fnFadeIn(elSlideNext,0); // trigger fade
	}
}

// fade in a specified element
function fnFadeIn(el,flOpacity) {
	boFadeActive = true;
	if (boSlideGallery) {
		elCaption.innerHTML = '';
	}
	fnSetOpacity(el,flOpacity);
	flOpacity = flOpacity + inIncrement;
	if (!boSlideshowPlay) { // speed up slide transitionif not currently in autoplay
		flOpacity = flOpacity + (inIncrement * 3);
	}
	if (flOpacity < 1) { // keep fading with updated opacity
		clearTimeout(t);
		t = setTimeout(function() {
			fnFadeIn(el,flOpacity);
		}, inStepTime);
	} else { // fade complete
		if (boSlideGallery) { // change caption after faded in
			elCaption.innerHTML = arImageData[inSlideNext][1];
		}
		boFadeActive = false;
		fnSlideSwitch(); // after completed fade - switch slides around
	}
}

// shuffle slides for next cycle
function fnSlideSwitch() {
	elSlidePrevious.src = arImageData[inSlideNext][0]; // move new slide to previous slide
	fnSetOpacity(elSlideNext,0); // hide next slide
		if (boSlideshowPlay) {
		clearTimeout(t);
		t = setTimeout(function() { // delay then go to next slide if in autoplay
			if (boSlideshowPlay) {
				fnSlideTransition(1);
			}
	}, inShowDuration);
	}
}



// BUTTON PRESSES__________________________________________________________________________

// thumbnail
function fnSlideshowGalleryThumb() {
	if (!boFadeActive) {
		boSlideshowPlay = false;
		fnClassSwap(elControls, 'play', 'pause');
		if (inSlideNext != fnWhichSelected(this.parentNode)) { // don't trigger if clicking the already selected slide
			inSlideNext = fnWhichSelected(this.parentNode);
			fnSlideTransition(0);
		}
	}
	return false;
}

// next
function fnSlideshowControlNext() {
	boSlideshowPlay = false;
	fnClassSwap(elControls, 'play', 'pause');
	fnSlideTransition(1);
}

// previous
function fnSlideshowControlPrevious() {
	boSlideshowPlay = false;
	fnClassSwap(elControls, 'play', 'pause');
	fnSlideTransition(-1);
}

// pause
function fnSlideshowControlPause() {
	boSlideshowPlay = false;
	fnClassSwap(elControls, 'play', 'pause');
}

// play
function fnSlideshowControlPlay() {
	boSlideshowPlay = true;
	fnClassSwap(elControls, 'pause', 'play');
	fnSlideTransition(1);
}



// UTILITIES________________________________________________________________________________

// add an increment to an item and find new location in list
function fnNewItem(list,item,increment) {
	item = item + increment;
	while (item >= list.length) {item = item - list.length;}
	while (item < 0) {item = item + list.length;}
	return item;
}

// identify an element on the page by ID
function fnGet(which) {
	return document.getElementById(which);
}

// use DOM to insert an element AFTER another
function insertAfter(targetElement,newElement) {
	var parent = targetElement.parentNode;
	if(parent.lastchild == targetElement) {
		parent.appendChild(newElement);
	} else {
		parent.insertBefore(newElement, targetElement.nextSibling);
	}
}

// cross-browser assignment of opacity
function fnSetOpacity(el,flOpacity) {
	if (document.body.style.opacity !== undefined) {
		el.style.opacity = flOpacity;
	} 
	if (document.body.style.MozOpacity !== undefined) {
		el.style.MozOpacity = flOpacity; // Mozilla
	}
	if (document.body.style.filter !== undefined) {
		el.style.filter = 'alpha(opacity=' + flOpacity * 100 + ')'; // Explorer
	}
}

// swap specified classnames
function fnClassSwap(el, classOld, classNew) {
  el.className = el.className.replace(new RegExp(classOld, 'g'), classNew);
}

// determine which place in the parent group this item is
function fnWhichSelected(elSelected) {
	var arItems = elSelected.parentNode.getElementsByTagName(elSelected.tagName);
	for (i=0, j=arItems.length; i<j; i++) {
		if (elSelected == arItems[i]) {
			return i;
		}
	}
}
