function ImageFader (id, image_list) {

	//-------------------------------
	// Member variables
	//-------------------------------
	var div_id = id;

	var images = image_list
	var imageArray = new Array (image_list.length);

	var faderDiv = document.getElementById(div_id);
	var currentImageImg = document.getElementById(div_id + "_currentImage");
	var nextImageImg = document.getElementById(div_id + "_nextImage");

	var currentImage = 0;
	var nextImage = 0;

	var FADE_STEP = 5;
	var FADE_INTERVAL = 100;
	var SLIDESHOW_DELAY = 2500;

	var loading = 0;

	var pause = false;
	var loop = true;
	var fading = false;

	var pingpong = true;

	// a hack to make setInterval/setTimeout work right.
	var thisObj = this;

	//-------------------------------
	// Methods
	//-------------------------------
	this.startShow = startShow;
	this.loadImages = loadImages;
	this.doSlideShowPause = doSlideShowPause;
	this.fadeUp = fadeUp;
	this.crossFade = crossFade;
	this.flipImage = flipImage;
	this.slideShowMode = slideShowMode;
	this.rotateImageNext = rotateImageNext;
	this.rotateImagePrev = rotateImagePrev;
	this.waitForFade = waitForFade;
	this.gotoNext = gotoNext;
	this.gotoNext_p2 = gotoNext_p2;
	this.gotoPrev = gotoPrev;
	this.gotoPrev_p2 = gotoPrev_p2;
	this.setElementOpacity = setElementOpacity

	//-------------------------------
	//Method defs.
	//-------------------------------
	function loadImages () {

		// if loading == length then we have loaded 
		// all images.
		if (loading >= imageArray.length) {
			loading += 2;
			return;
		}

		//save and then increment loading.
		var to_load = loading;
		loading++;
		imageArray[to_load] = new Image ();
		imageArray[to_load].onload = loadImages;
		imageArray[to_load].src = image_list[to_load];
	}

	function startShow () {
		// Make sure the first image is loaded. If not,
		// set a timeout to recall this function in 100 
		// miliseconds.
		if (loading <= 1) {
			window.setTimeout(function(){thisObj.startShow()},500);
			return;
		}

		currentImage = images.length - 1;
		nextImage = 0;

		setElementOpacity (currentImageImg,100);
		setElementOpacity (nextImageImg,0);

		currentImageImg.src = images[currentImage];
		nextImageImg.src = images[nextImage];

		fadeUp (FADE_STEP,FADE_INTERVAL,100);
		waitForFade (slideShowMode,SLIDESHOW_DELAY);

	}

	function slideShowMode () {

		if (pause) {
			waitForFade (slideShowMode,200);
			return;
		}

		if (nextImage >= loading - 2) {
			window.setTimeout(function(){thisObj.slideShowMode()},500);
			return;
		}
		
		rotateImageNext ();

		crossFade(FADE_STEP,FADE_INTERVAL,0)
		waitForFade (slideShowMode,SLIDESHOW_DELAY);
	}

	function doSlideShowPause()  {
		if(pause) {
			pause = false;
		} else {
			pause = true;
		}
	}

	function waitForFade (to_call, delay) {
		if (fading) {
			window.setTimeout(function(){thisObj.waitForFade (to_call,delay)},200);
			return;
		}

		if (delay == 0) {
			to_call ();
		} else {
			window.setTimeout(to_call,delay);
		}
	}

	function rotateImageNext () {
		pingpong = !pingpong;

		currentImage = nextImage;
		nextImage++;
		if(nextImage >= images.length) {
			nextImage=0;
		}

		if (pingpong) {
			nextImageImg.style.marginTop = imageArray[nextImage].style.marginTop;
			nextImageImg.src = images[nextImage];
		} else {
			currentImageImg.style.marginTop = imageArray[nextImage].style.marginTop;
			currentImageImg.src = images[nextImage];
		}
	}

	function rotateImagePrev () {
		pingpong = !pingpong;

		currentImage = nextImage;
		nextImage--;
		if(nextImage < 0) {
			nextImage = images.length - 1;
		}

		if (pingpong) {
			nextImageImg.style.marginTop = imageArray[nextImage].style.marginTop;
			nextImageImg.src = images[nextImage];
		} else {
			currentImageImg.style.marginTop = imageArray[nextImage].style.marginTop;
			currentImageImg.src = images[nextImage];
		}
	}
	
	function gotoNext()  {
		//cancel the current loop. 
		pause = true;

		buttons.buttonDown ();
		buttons.makePausing ();

		waitForFade (gotoNext_p2,50);
	}

	function gotoNext_p2 () {
		if (nextImage >= loading - 2) {
			window.setTimeout(function(){thisObj.gotoNext_p2()},500);
			return;
		}
		rotateImageNext ();

		flipImage (FADE_INTERVAL,0);
	}

	function gotoPrev () {
		//cancel the current loop. 
		pause = true;

		waitForFade (gotoPrev_p2,0);
	}

	function gotoPrev_p2 () {
		if ((nextImage == 0) && (loading < images.length)) {
			messageDiv.innerHTML = "<br>Can't gotoPrev. Not enough images loaded." + messageDiv.innerHTML;
			window.setTimeout(function(){thisObj.gotoPrev_p2()},500);
			return;
		}

		rotateImagePrev ();

		flipImage (FADE_INTERVAL,0);
	}

	function fadeUp (step,interval,current_opacity) {
		fading = true;

		var working_image;
		if (pingpong) {
			working_image = nextImageImg;
		} else {
			working_image = currentImageImg;
		}

		current_opacity += step;
		if (current_opacity > 100) current_opacity = 100;
				
		setElementOpacity (working_image,current_opacity);
	
		if (current_opacity < 100) {
			setTimeout(function(){thisObj.fadeUp(step,interval,current_opacity)},interval);
		} else {
			fading = false;	
		}
	}
	
	function crossFade (step,interval,current_opacity) {
		fading = true;

		var old_image;
		var new_image;
		if (pingpong) {
			old_image = currentImageImg;
			new_image = nextImageImg;
		} else {
			old_image = nextImageImg;
			new_image = currentImageImg;
		}

		current_opacity += step;
		if (current_opacity > 100) current_opacity = 100;
			
		setElementOpacity (old_image,100-current_opacity);

		setElementOpacity (new_image,current_opacity);

		if (current_opacity < 100) {
			setTimeout(function(){thisObj.crossFade(step,interval,current_opacity)},interval);
		} else {
			fading = false;	
		}
	}

	function flipImage (interval,state) {
		fading = true;

		var old_image;
		var new_image;
		if (pingpong) {
			old_image = currentImageImg;
			new_image = nextImageImg;
		} else {
			old_image = nextImageImg;
			new_image = currentImageImg;
		}

		if (state == 0) {
			setElementOpacity (old_image,0);

			state++;
			setTimeout(function(){thisObj.flipImage(interval,state)},2*interval);
		} else if (state = 1) {
			setElementOpacity (new_image,100);

			state++;
			fading = false;		
		}

	}

	function setElementOpacity (elm, opacity) {
		elm.style.opacity = opacity/100;
		elm.style.filter="alpha(opacity=" + opacity + ")";
		elm.style.MozOpacity = opacity/100;
	}
}

function StatusMessage (id) {
	var div_id = id;

	var statusDiv = document.getElementById(div_id);

	this.setMessage = setMessage;

	function setMessage (new_message) {
		statusDiv.innerHTML = new_message;
	}
}
