// JavaScript Document

// default parameters
var DEFAULT_SEQUENCE_DELAY = 3000;
var DEFAULT_FADE_DELAY = 200;
var DEFAULT_FADE_MAX = 100;
var DEFAULT_FADE_MIN = 20;


/*****************************************
 *	class: ImageChanger
 *
 *	cycles through an array of images,
 * using the Spry Fade effect widget for
 * transitions
 *
 *	Properties:
 * - sequenceDelay (int): time (in milliseconds) to wait before next image transition; default is 3000
 * - fadeDelay (int): time (in milliseconds) to spend on fade transition; default is 200
 * - maximumOpacity (int): maximum opacity percentage; default is 100 (100% = no transparency)
 * - minimumOpacity (int): minimum opacity percentage; default is 20 (0% = invisible)
 * - interval (object): stores the cycle interval; only needed if you want to stop the cycle
 *					(eg: clearInterval(this.interval); )
 * - array (String[]): array of strings with the paths (.src property) of the images to use
 * - randomize (boolean): determines whether next image will be randomly selected from array, instead of sequentially
 * - requireDiffRand (boolean): if using random images, should selection require a change 
 *					(if random function returns current position, run again)
 * - position (int): the current position in the array
 *****************************************/
 

/*******************************
 *	ImageChanger::constructor(String, String[], boolean)
 *
 *	@param imageId (String) - the id 
 *		of the image element that will change
 *	@param imageArray (String[]) - an
 *		array of strings with the paths
 *		(ie .src property) of the images to use
 *	@param useRand (boolean) - true makes the
 *		images select randomly, false or no arg
 *		makes the images cycle in the same order
 *		as the array
 ******************************/
ImageChanger = function(imageId, imageArray, useRand) {
	this.sequenceDelay = DEFAULT_SEQUENCE_DELAY;
	this.fadeDelay = DEFAULT_FADE_DELAY;
	this.maximumOpacity = DEFAULT_FADE_MAX;
	this.minimumOpacity = DEFAULT_FADE_MIN;
	
	this.interval = null;
	
	this.element = document.getElementById(imageId);
	this.array = [];
	if (imageArray)
		this.array = imageArray;
	
	this.randomize = (useRand!=null ? useRand : false);
	this.requireDiffRand = (this.randomize && this.array.length > 1);
	this.position = 0;
}


/*********************************
 *	ImageChanger::setImages(String, String, int, int)
 *
 *	generate image paths when many images with simple naming pattern
 *	EX: setImages('images/img', '.jpg', 1, 16);
 *	above call would generate array containing 'images/img1.jpg' thru 'images/img16.jpg'
 ********************************/
ImageChanger.prototype.setImages = function(prefix, suffix, startingNum, endingNum) {
	for (var j=startingNum; j<=endingNum; j++) {
		this.array.push(prefix + j + suffix);
	}
}

/*********************************
 *	ImageChanger::setFadeAttr(int, int, int, int)
 *
 *	@param sequenceDelaySecs (int): seconds to wait before next image transition
 *	@param fadeDelayMillis (int): milliseconds to spend on fade transition
 *	@param fadeMax (int): maximum opacity percentage
 *	@param fadeMin (int): minimum opacity percentage
 ********************************/
ImageChanger.prototype.setFadeAttr = function(sequenceDelaySecs, fadeDelayMillis, fadeMax, fadeMin) {
	this.sequenceDelay = sequenceDelaySecs * 1000;
	this.fadeDelay = fadeDelayMillis;
	this.maximumOpacity = fadeMax;
	this.minimumOpacity = fadeMin;
}

// returns random array position
ImageChanger.prototype.randomImage = function() {
	var rand = Math.random() * this.array.length-1;
	return Math.ceil(rand);
}

// returns random array position OTHER THAN current position
ImageChanger.prototype.randomDiff = function() {
	var diff = this.position;
	while (diff == this.position) {
		diff = this.randomImage();
	}
	return diff;
}

// returns next array position, or first if at end
ImageChanger.prototype.sequentialImage = function() {
	var next = this.position+1;
	if (next == this.array.length)
		next = 0;
	return next;	
}

// transitions to another image
ImageChanger.prototype.transition = function() {
	if (this.randomize)
		this.position = this.requireDiffRand ? this.randomDiff() : this.randomImage();
	else
		this.position = this.sequentialImage();
	
	fadeImage(this.array[this.position], this.element.id, this.fadeDelay, this.minimumOpacity);
}

// begins transition sequence
ImageChanger.prototype.start = function() {
	this.interval = initRepitition(this);
}

// preloads all images in array (prevents waiting for image load during sequence)
ImageChanger.prototype.preload = function(width, height) {
	for (var i in this.array) {
		var img = new Image(width, height);
		img.src = this.array[i];
	}
}



/****************************************
 *	GLOBAL FUNCTIONS
 ***************************************/


/*******************************
 *	initRepitition(ImageChanger)
 *	
 *	initializes sequence (exists because you can't run setInterval on a class method)
 *	@param imgChanger (ImageChanger): an ImageChanger instance
 *	@returns the interval handle
 ******************************/
function initRepitition(imgChanger) {
	var intvFn = function() { imgChanger.transition(); }
	var interval = setInterval(intvFn, imgChanger.sequenceDelay);
	return interval;
}

/*******************************
 *	swapImage(String, String, Function)
 *
 *	replaces image source, then executes function
 *	@param imgId (String): the id of the image to change
 *	@param imgSrc (String): the path to the new image
 *	@param func (Function): the function to execute at end
 ******************************/
function swapImage(imgId, imgSrc, func) {
	document.getElementById(imgId).src = imgSrc;
	if (func) {
		func();
	}
}

/********************************
 *	fadeImage(String, String, int, int)
 *
 *	fades out current image, replaces image src, fades in new image
 *	@param imgSrc (String): source of new image
 *	@param imgId (String): the id of the image to change
 *	@param fadeTime (int): time (in milliseconds) to complete fade transition
 *	@param minOpacity (int): the opacity level for transition to drop to/rise from
 *******************************/
function fadeImage(imgSrc, imgId, fadeTime, minOpacity) {
	Spry.Effect.DoFade(imgId, {duration: fadeTime, from:100, to:minOpacity, finish:function(){swapImage(imgId, imgSrc, function(){Spry.Effect.DoFade(imgId, {duration:fadeTime, from:minOpacity, to:100})}); } });
}