/**
 * Initialises a slide show
 *
 * @param String prefix the HTML id prefix used on each slide
 * @param int msec the interval between successive slides
 * @param int opacitySteps the number of opacity transition steps
 * @param int name the name of the JavaScript object instantiated by this constructor
 */
function Jsslideshow(/*optional string*/ prefix, /*optional int*/ msec, /*optional int*/ opacitySteps, /*optional string*/ name)
{
	this.prefix = prefix ? prefix : "myJsslideshow";
	this.name = name? name : this.prefix;
	this.default_interval = msec ? parseInt(msec) : 3500;

	this.fadeInDelay = 200; // Setting this to 0 will suppress fade out. Positive values will issue fade in this amount of milliseconds after starting fade out.
	this.fadeInTime = 200; // Total time to fade in in milliseconds
	this.fadeOutTime = 400; // Total time to fade out in milliseconds
	this.opacitySteps = opacitySteps || 10;

	this.autoSlide = false;
	this.selected = 0;

	this.size = this.getSize();
}


Jsslideshow.prototype.getElem = function(i)
{
	var elem = document.getElementById(this.prefix + '-' + i);
	return elem ? elem : false;
}


Jsslideshow.prototype.getVisible = function()
{
	for (var i = 0; i < this.size; i++)
	{
		var elem = this.getElem(i);
		if (elem && !hasClass(elem, "hidden"))
		{
			return i;
		}
	}
	return false;
}


Jsslideshow.prototype.getSize = function()
{
	var i = 0;
	while (true)
	{
		var elem = this.getElem(i);
		if (!elem)
		{
			return i;
		}
		++i;
	}
}


// Starts the slideshow
// msec (optional) is the interval in milliseconds. Defaults to the value specified at the top
// NOTE: If the slideshow is already started, it will essentially continue, but with the new msec interval
Jsslideshow.prototype.autoStart = function(msec)
{
	if (!this.size)
	{
		return;
	}
	this.selected = this.getVisible();

	if (this.timer)
		this.autoStop();

	if (msec)
		this.default_interval = msec;

	this.autoSlide = true;

	this.autoNext();

}


Jsslideshow.prototype.autoNext = function()
{
	if (this.autoSlide)
		this.timer = setTimeout(this.name + ".showNext();", this.default_interval);
}


// Stops the slideshow
Jsslideshow.prototype.autoStop = function()
{
	if (this.timer)
		this.timer = clearTimeout(this.timer);
	this.autoSlide = false;
}


// Starts or stops the slideshow
Jsslideshow.prototype.autoToggle = function()
{
	if (this.autoSlide)
		this.autoStop();
	else
		this.autoStart();
}


// Shows the previous slide
Jsslideshow.prototype.showPrev = function(i)
{
	if (i == undefined)
		i = this.selected;
	else if (i == this.selected)
		return;

	i = (i - 1 + this.size )% this.size; // i-- between 0 and this.size

	if (!this.getElem(i))
		setTimeout(this.name + ".showPrev("+i+")", 10);
	else
		this.show(i);
}


// Shows the next slide
// Rewinds to the beginning when reaching the end
Jsslideshow.prototype.showNext = function(i)
{
	if (i == undefined)
	{
		if (this.selected == undefined)
			this.selected = this.getVisible();
		i = this.selected;
	}
	else if (i == this.selected)
		return;

	i = (i + 1 ) % this.size; // i++ between 0 and this.size

	if (!this.getElem(i))
		setTimeout(this.name + ".showNext("+i+")", 10);
	else
		this.show(i);
}


// Shows a specific slide (fades in)
Jsslideshow.prototype.show = function(i)
{
	if (i == this.selected)
		return;
	var elem = this.getElem(i);
	if (elem)
	{
		if (this.fadeInDelay > 0)
			this.fadeOut(this.selected);
		setTimeout(this.name + ".fadeIn("+i+")", this.fadeInDelay);

		var nav_elem = document.getElementById(this.prefix + "_navbar_select-" + this.selected);
		if (nav_elem)
			removeClass(nav_elem, "selected");

		var nav_elem = document.getElementById(this.prefix + "_navbar_select-" + i);
		if (nav_elem)
			addClass(nav_elem, "selected");
	}
}


// Hides a specific slide (immediately)
Jsslideshow.prototype.hide = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		if (!hasClass(elem, "hidden"))
			addClass(elem, "hidden");
	}
}


Jsslideshow.prototype.fadeIn = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade in
		{
			addClass(elem, "opacity0");
			removeClass(elem, "hidden");
			addClass(elem, "on_top");
			this.fadeIn(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);

		if (opacity > 100-(100/this.opacitySteps))	// Ending fade in
		{
			this.hide(this.selected);
	 		this.selected = i;
	 		removeClass(elem, opacity_class);
	 		removeClass(elem, "on_top");
	 		this.autoNext();
			return;
		}

		opacity = opacity + parseInt(100 / this.opacitySteps);
		addClass(elem, "opacity" + opacity);
		removeClass(elem, opacity_class);

		setTimeout(this.name + ".fadeIn("+i+")", parseInt(this.fadeInTime / this.opacitySteps));
	}
}


Jsslideshow.prototype.fadeOut = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade out
		{
			addClass(elem, "opacity100");
			this.fadeOut(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);

		if (opacity < 100/this.opacitySteps)
		{
			removeClass(elem, opacity_class);
			this.hide(i);
			return;
		}

		opacity = opacity - parseInt(100 / this.opacitySteps);
		addClass(elem, "opacity" + opacity);
		removeClass(elem, opacity_class);

		setTimeout(this.name + ".fadeOut("+i+")", parseInt(this.fadeOutTime / this.opacitySteps));
	}
}


myJsslideshow = new Jsslideshow("myJsslideshow");
