function Gallery(images, jQuery, options)
{
	var defaultOptions = {
		hashPrefix: "",
		prevTransition: 'Switch',
		nextTransition: 'Switch',
		gotoTransition: 'Switch'
	};
	this.id = Gallery.instances.length;
	Gallery.instances[this.id] = this;
	this.images = images;
	this.jQuery = jQuery;
	this.jQuery.extend(defaultOptions, options);
	this.hashPrefix = defaultOptions.hashPrefix;
	this.prevTransition = defaultOptions.prevTransition;
	this.nextTransition = defaultOptions.nextTransition;
	this.gotoTransition = defaultOptions.gotoTransition;
	this.className = this.constructor.toString().substring(9, this.constructor.toString().indexOf("("));
	this.timer = undefined;
	this.timeout = 3000;
	this.silent = false;
	this.totalNumber = this.images.length;
	
	Gallery.prototype.id;
	Gallery.prototype.className;
	Gallery.prototype.images;
	Gallery.prototype.jQuery;
	Gallery.prototype.timer;
	Gallery.prototype.timeout;
	Gallery.prototype.silent;	
	Gallery.prototype.currentNumber;
	Gallery.prototype.totalNumber;
	
	Gallery.prototype.run = function(number, silent)
	{
		if(this.timer == undefined)
		{
			var reference = this;
			this.currentNumber = (number == undefined) ? false : number;
			if(this.currentNumber === false)
			{
				var hash = parseInt(this.jQuery.address.value().substr(this.hashPrefix.length));
				this.currentNumber = (isNaN(hash)) ? 0 : hash;
			}
			this.silent = (silent == undefined) ? false : silent;
			this.timer = setTimeout(reference.className + ".getObject(" + reference.id + ").keepRunning();", 0);
		}
	}

	Gallery.prototype.keepRunning = function()
	{
		this.currentNumber = this.increaseNumber(this.currentNumber);
		this.change('Fade');
	}
	
	Gallery.prototype.change = function(functionName, restart)
	{
		var restart = (restart != undefined) ? restart : true;
		try
		{
			eval("this.transition" + functionName + "(" + restart + ")");
		} catch(error)
		{
			alert("this.transition" + functionName + "() is not a specified function of this class.")
		}
	}

	Gallery.prototype.updateNumber = function(number)
	{
		this.currentNumber = number;
		if(this.jQuery.isFunction(this.update)) this.update(this.currentNumber);
	}

	Gallery.prototype.decreaseNumber = function(number)
	{
		return (number < 1) ? this.totalNumber - 1 : number - 1;
	}
	
	Gallery.prototype.increaseNumber = function(number)
	{
		return (number > this.totalNumber - 2) ? 0 : number + 1;
	}

	Gallery.prototype.pause = function()
	{
		this.timer = clearTimeout(this.timer);
	}

	Gallery.prototype.stop = function()
	{
		this.images.stop(true, true);
		this.pause();
	}

	Gallery.prototype.prev = function()
	{
		this.switchPicture(this.decreaseNumber(this.currentNumber), this.prevTransition);
	}

	Gallery.prototype.next = function()
	{
		this.switchPicture(this.increaseNumber(this.currentNumber), this.nextTransition);
	}
	
	Gallery.prototype.goto = function(number)
	{
		if(number < this.totalNumber && number > -1) this.switchPicture(number, this.gotoTransition);
	}

	Gallery.prototype.switchPicture = function(number, transition)
	{
		var reference = this;
		var number = number;
		var restart = false;
		if(this.timer != undefined)
		{
			this.stop();
			restart = true;
		}
		this.updateNumber(number);
		this.change(transition, restart);
	}
	
	Gallery.prototype.setTimeout = function()
	{
		var reference = this;
		reference.timer = setTimeout(reference.className + ".getObject(" + reference.id + ").keepRunning();", reference.timeout);
	}
	
	Gallery.prototype.transitionFade = function(restart)
	{
		var reference = this;
		var restart = restart;
		this.images.each(function(i)
		{
			if(reference.currentNumber != i)
			{
				reference.jQuery(this).fadeOut(reference.timeout / 3);
			}
		});
		this.images.eq(this.currentNumber).fadeIn(reference.timeout / 3, function()
		{
			if(!reference.silent)
			{
				reference.jQuery.address.value(reference.hashPrefix.toString() + reference.currentNumber.toString());
			}
			reference.updateNumber(reference.currentNumber);
			if(restart) reference.setTimeout();
		}).children("img").fadeIn(reference.timeout / 3);
	}

	Gallery.prototype.transitionSwitch = function(restart)
	{
		var reference = this;
		this.images.eq(this.currentNumber).show().children("img").show();
		this.images.each(function(i)
		{
			if(i != reference.currentNumber)
			{
				reference.jQuery(this).hide();
			}
		});
		if(!this.silent)
		{
			this.jQuery.address.value(this.hashPrefix.toString() + this.currentNumber.toString());
		}
		this.updateNumber(this.currentNumber);
		if(restart) reference.setTimeout();
	}
}

Gallery.instances = new Array();

Gallery.getObject = function(id)
{
	if(this.instances[id]) return this.instances[id];
}
