var slideshow = {
	defaultoptions: {
		cycle: false,
		container: null,
		source: 'container', //json //function
		nextButton: null,
		prevButton: null,
		imagearray: null,
		imagefunction: null,
		indexedButtons: null,
		beforeTransition: null,
		afterTransition: null,
		cycleSpeed: 7000,
		transitionSpeed: 2000,
		transition: 'fade'
	},
	create: function (customoptions) {

		var
			options = jQuery.extend(jQuery.extend({}, slideshow.defaultoptions), customoptions),
			container = options.container, //container with images
			current, //current image
			_animating = false,
			_timeout, //timeout

		s = {
			css: {
				shownimage: {'position': 'absolute', 'left': 0, 'top': 0, 'z-index': 15},
				hiddenimage: {'position': 'absolute', 'left': 0, 'top': 0, 'z-index': 5}
			},
			queueImage: function (image) {
				var loaded = false, timed = false;

				//preload image
				image.load(function () {
					loaded = true;
					if (timed) {
						//if loading took longer then the timeout
						s.showImage(image);
					}
				});
				//set timeout
				_timeout = window.setTimeout(function () {
					timed = true;
					if (loaded) {
						//if loading took shorter then the timeout
						s.showImage(image);
					}
				}, options.cycleSpeed);
			},

			queueNext: function () {
				s.queueImage(s.getNextImage());
			},

			getNextImage: function () {
				var next, temp;

				switch (options.source) {
					case 'container':
						next = current.next();
						if (next.length === 0) {
							next = container.children('img').eq(0);
						}
						break;
					case 'function':
						next = $('<img>').attr('src', options.imagefunction());
						break;
					case 'json':
						temp = options.imagearray.shift(); //get first in row
						next = $('<img>').attr('src', temp);
						options.imagearray.push(temp); //push to last in row
						break;
					default:
						console.log('{slideshow}: Unknown image source');
				}

				next.css(s.css.hiddenimage).appendTo(container);

				return next;
			},

			showByIndex: function (index) {
				var next = container.children('img').eq(index);

				s.queueImage(next);
			},

			showImage: function (next, transition) {

				//callback function for when animation is done
				var animationDone = function () {
					var previous = current;
					current = next;
					_animating = false;

					if (options.afterTransition !== null) {
						options.afterTransition(previous, current);
					}

					current.css('z-index', 15);
					if (options.source === 'json' || options.source === 'function') {
						previous.remove();
					} else {
						previous.css({'z-index': 5, 'opacity': 1});
					}

					if (options.cycle) {
						s.queueNext();
					}
				};

				//set default transition
				if (typeof transition === 'undefined' || transition === null) {
					transition = options.transition;
				}

				window.clearTimeout(_timeout);

				next.css({'z-index': 10, opacity: 1});

				if (options.indexedButtons !== null) {
					current.removeClass('current');
					next.addClass('current');
				}
				if (options.beforeTransition !== null) {
					options.beforeTransition(current, next);
				}

				_animating = true;
				switch (transition) {
					case 'fade':
						current.animate({opacity: 0}, options.transitionSpeed, animationDone);
						break;
					default:
						console.log('{slideshow}: Unknown transition');
				}

			}
		};

		//CSS
		container.width(container.width());
		container.height(container.height());
		if (container.css('position') !== 'absolute' && container.css('position') !== 'fixed') {
			container.css('position', 'relative');
		}
		current = container.children('img').eq(0).css(s.css.shownimage);
		container.children('img').not(':first').css(s.css.hiddenimage).hide();

		//CONTROLS
		if(options.nextButton !== null) {
			options.nextButton.click(function (e) {
				e.preventDefault();
				if (_animating) { return false; }
				if (!_animating) {
					s.queueImage(s.getNextImage());
				}
				return false;
			});
		}
		if(options.prevButton !== null) {
			options.prevButton.click(function (e) {
				e.preventDefault();
				if (!_animating) {
					//TODO
				}
				return false;
			});
		}
		if(options.indexedButtons !== null) {
			options.indexedButtons.each(function (index) {
				options.indexedButtons.eq(index).click(function (e) {
					e.preventDefault();
					if (!_animating) {
						s.showByIndex(index);
					}
					return false;
				});
			});
		}

		//CYCLE
		if(options.cycle) {
			s.queueNext();
		}

		return s;
	}
};
