/*
	ELSPhotoTransitioner.js
	
	The ELSPhotoTransitioner class provides an image transition object with a
	library of transitions that it can swap between one image and another.
	
	This class provides the following events, onStart, onPause, onStop,
	onFinish. onStop will be called when the object is told to stop playback,
	while onFinish will be called when the object finishes the transition
	naturally.
*/
function ELSPhotoTransitioner(theTransitionImage, theCurrentImage, theOptions)
{
	// instance identifiers
	var instanceSelf = this;
	var instanceClass = this.constructor.prototype;
	var instanceIdentifier;
	
	// public instance accessors
	instanceSelf.start = start;
	instanceSelf.stop = stop;
	instanceSelf.pause = pause;
	instanceSelf.resume = resume;
	instanceSelf.animate = animate;
	instanceSelf.getElement = getElement;
	instanceSelf.setOptions = setOptions;
	instanceSelf.setTransitionImage = setTransitionImage;
	instanceSelf.setTransitionImageAndStart = setTransitionImageAndStart;
	instanceSelf.setTransitionImageAndStartWithDelay = setTransitionImageAndStartWithDelay;
	
	// instance members
	var photoContainer;
	var transitionContainer;
	var currentImage;
	var transition;
	var transitionImage;
	var transitionInterval;
	var transitionSpeed;
	var startDelayTimeout;
	var eventManager;
	
	// set up the event manager
	eventManager = new ELSEventManager();
	
	// set up the event methods
	instanceSelf.addEventListener = eventManager.addEventListener;
	instanceSelf.removeEventListener = eventManager.removeEventListener;
	
	// set up the default values
	transition = "fadeover";
	transitionSpeed = 25;
	
	// instance methods
	function getElement()
	{
		return photoContainer;
	}
	function setOptions(theOptions)
	{
		try
		{
			if (theOptions["id"])
			{
				photoContainer.id = theOptions["id"];
				transitionContainer.id = theOptions["id"] + "Transition";
			}
			if (theOptions["width"])
			{
				photoContainer.style.width = theOptions["width"];
				transitionContainer.style.width = theOptions["width"];
			}
			if (theOptions["height"])
			{
				photoContainer.style.height = theOptions["height"];
				transitionContainer.style.height = theOptions["height"];
			}
			if (theOptions["backgroundColor"])
			{
				photoContainer.style.backgroundColor = theOptions["backgroundColor"];
				transitionContainer.style.backgroundColor = theOptions["backgroundColor"];
			}
			if (theOptions["transition"])
			{
				theTransition = theOptions["transition"];
			}
		}
		catch (exception)
		{
			// we don't care...
			//alert(exception);
		}
	}
	function setTransitionImage(theImage)
	{
		// check to make sure this is a string
		if ((typeof theImage == "string") && (theImage != ""))
		{
			transitionImage = theImage;
		}
		else if ((theImage) && (theImage.nodeType == 1) && (theImage.src != ""))
		{
			transitionImage = theImage.src;
		}
		else
		{
			transitionImage = null;
		}
		
		// set the opacity of the top layer to 0, so that it is hidden before
		//	the start of the transition
		if (window.ActiveXObject)
		{
			transitionContainer.style.filter = "alpha(opacity=0)";
		}
		transitionContainer.style.opacity = 0;
	}
	function setTransitionImageAndStart(theImage)
	{
		// stop the previous transition
		stop();
		
		// set the transition image
		setTransitionImage(theImage);
		
		// start the transition immediately
		start();
	}
	function setTransitionImageAndStartWithDelay(theImage, theDelay)
	{
		// stop the previous transition
		stop();
		
		// set the transition image
		setTransitionImage(theImage);
		
		// start the transition after a delay
		startDelayTimeout = setTimeout("window.ELSPhotoTransitionerInstances[" + instanceIdentifier + "].start();", theDelay);
	}
	
	// animation methods
	function start()
	{
		// kill any previous transition
		// clear the fader interval
		try
		{
			// clear the interval
			clearInterval(transitionInterval);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		transitionInterval = null;
		// clear any start delay timeout
		try
		{
			// clear the interval
			clearTimeout(startDelayTimeout);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		startDelayTimeout = null;
		
		// start the transition
		startFade();
		
		// call any event listeners
		eventManager.callEventListeners("onStart");
	}
	function pause()
	{
		// cancel any timeouts/intervals
		// clear the fader interval
		try
		{
			// clear the interval
			clearInterval(transitionInterval);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		transitionInterval = null;
		// clear any start delay timeout
		try
		{
			// clear the interval
			clearTimeout(startDelayTimeout);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		startDelayTimeout = null;
		
		// if anyone cares about reseting a start delay, we send them the 
		//	onPause notification and leave it up to them to reset it
		
		// call any event listeners
		eventManager.callEventListeners("onPause");
	}
	function resume()
	{
		// continue where we left off with the transition
		// set the transition interval again
		transitionInterval = setInterval("window.ELSPhotoTransitionerInstances[" + instanceIdentifier + "].animate();", 1 * transitionSpeed);
		
		// call any event listeners
		eventManager.callEventListeners("onResume");
	}
	function stop()
	{
		// clear the fader interval
		try
		{
			// clear the interval
			clearInterval(transitionInterval);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		transitionInterval = null;
		// clear any start delay timeout
		try
		{
			// clear the interval
			clearTimeout(startDelayTimeout);
		}
		catch (exception)
		{
			// do nothing
			//alert(exception);
		}
		startDelayTimeout = null;
		
		// stop the transition
		stopFade();
		
		// call any event listeners
		eventManager.callEventListeners("onStop");
	}
	function finish()
	{
		// clear the fader interval
		clearInterval(transitionInterval);
		transitionInterval = null;
		
		// stop the transition
		stopFade();
		
		// call any event listeners
		eventManager.callEventListeners("onFinish");
	}
	function animate()
	{
		// animate this step of the transition
		animateFade();
	}
	
	// transition functions
	function startFade()
	{
		// set up the preconditions for the fade transition and start the
		//	animation interval
		
		// now set the transition image opacity
		transitionContainer.style.backgroundImage = "url(" + transitionImage + ")";
		if (window.ActiveXObject)
		{
			transitionContainer.style.filter = "alpha(opacity=0)";
		}
		transitionContainer.style.opacity = 0;
		
		// set the background options
		if (window.ActiveXObject)
		{
			photoContainer.style.filter = "alpha(opacity=100)";
		}
		photoContainer.style.opacity = 1;
		
		// determine if there is a change
		if (photoContainer.style.backgroundImage != transitionContainer.style.backgroundImage)
		{
			// start the fader
			// since set interval requires a string value, we will utilize a
			//	hack to call a variable that's local to the window and that we
			//	know the name of
			transitionInterval = setInterval("window.ELSPhotoTransitionerInstances[" + instanceIdentifier + "].animate();", 1 * transitionSpeed);
		}
		else
		{
			// the images are already the same, so we're finished
			finish();
		}
	}
	function animateFade()
	{
		// grab the opacity from the foreground
		var opacity = 0;
		if (transitionContainer.style.opacity > 0)
		{
			opacity = Math.ceil(transitionContainer.style.opacity * 1000);
		}
		
		// increment the opacity
		opacity += 50;
		// if we're in IE, double the rate
		if (window.ActiveXObject)
		{
			opacity += 100;
		}
		
		// check to see if we've reached 100%
		if (opacity > 1000)
		{
			opacity = 1000;
		}
		
		// set the image opacity
		if (window.ActiveXObject)
		{
			transitionContainer.style.filter = "alpha(opacity=" + Math.ceil(opacity / 10) + ")";
		}
		transitionContainer.style.opacity = (opacity / 1000);
		
		// determine we're we go from here
		if (opacity >= 1000)
		{
			// stop the animation
			finish();
		}
	}
	function stopFade()
	{
		// set the image as the background
		photoContainer.style.backgroundImage = transitionContainer.style.backgroundImage;
		
		// reset the opacity of the foreground
		if (window.ActiveXObject)
		{
			transitionContainer.style.filter = "alpha(opacity=0)";
		}
		transitionContainer.style.opacity = 0;
	}
	
	// constructor process
	// create a unique instance identifier, to allow us to id our element as
	//	provide a named agent that can handle the set interval timeouts
	// get the current count of unique identifiers
	if (!window.ELSPhotoTransitionerInstances)
	{
		window.ELSPhotoTransitionerInstances = new Array();
	}
	instanceIdentifier = window.ELSPhotoTransitionerInstances.length;
	window.ELSPhotoTransitionerInstances[window.ELSPhotoTransitionerInstances.length] = instanceSelf;
	
	// create the container element and the foreground element
	photoContainer = document.createElement("div");
	photoContainer.className = "ELSPhotoTransitioner";
	photoContainer.style.backgroundPosition = "50% 50%";
	photoContainer.style.backgroundRepeat = "no-repeat";
	
	// set up a reference back to this object within the photo container
	photoContainer.ELSPhotoTransitioner = instanceSelf;
	
	// set up the current image
	if ((theCurrentImage) && (typeof theCurrentImage == "string") && (theCurrentImage != ""))
	{
		currentImage = theCurrentImage;
		
		// try to set the background of our element to this image
		photoContainer.style.backgroundImage = "url(" + currentImage + ")";
	}
	else if ((theCurrentImage) && (theCurrentImage.nodeType == 1) && (theCurrentImage.src != ""))
	{
		// assume we have an image object that we need to take over
		currentImage = theCurrentImage.src;
		
		// try to set the background of our element to this image
		photoContainer.style.backgroundImage = "url(" + currentImage + ")";
		
		// determine if the image has a parent element
		if (theCurrentImage.parentNode)
		{
			// try to replace the image with our element
			theCurrentImage.parentNode.replaceChild(photoContainer, theCurrentImage);
		}
	}
	
	// add a second layer to the transitioner element
	transitionContainer = photoContainer.cloneNode(false);
	photoContainer.appendChild(transitionContainer);
	
	// determine if we have any options specified
	setOptions(theOptions);
	
	// set up the remaining settings
	if (theTransitionImage)
	{
		setTransitionImage(theTransitionImage);
	}
}
