var Multibox = (function()
{
	// Global variables, accessible to Slimbox only
	var win = window, ie6 = Browser.ie6, options, images, activeImage = -1, activeURL, prevImage, nextImage, compatibleOverlay, middle, centerWidth, centerHeight,

	// Preload images
	preload = {}, preloadPrev = new Image(), preloadNext = new Image(),

	// DOM elements
	overlay, center, image, img, sizer, prevLink, nextLink, bottomContainer, bottom, caption, number,

	// Effects
	fxOverlay, fxResize, fxImage, fxBottom;

	/*
		Initialization
	*/

	win.addEvent("domready", function() {
		// Append the Multibox HTML code at the bottom of the document
		$(document.body).adopt(
			$$(
				overlay = new Element("div#lbOverlay", {events: {click: close}}),
				center = new Element("div#lbCenter"),
				bottomContainer = new Element("div#lbBottomContainer")
			).setStyle("display", "none")
		);

		image = new Element("div#lbImage").inject(center).adopt(
			img = new Element("img"),
			prevLink = new Element("a#lbPrevLink[href=#]", {events: {click: previous}}),
			nextLink = new Element("a#lbNextLink[href=#]", {events: {click: next}})
		);
		//img = new Element("img");

		bottom = new Element("div#lbBottom").inject(bottomContainer).adopt(
			new Element("a#lbCloseLink[href=#]", {events: {click: close}}),
			caption = new Element("div#lbCaption"),
			number = new Element("div#lbNumber"),
			new Element("div", {styles: {clear: "both"}})
		);
	});


	/*
		Internal functions
	*/

	function position() {
		var scroll = win.getScroll(), size = win.getSize();
		$$(center, bottomContainer).setStyle("left", scroll.x + (size.x / 2));
		if (compatibleOverlay) overlay.setStyles({left: scroll.x, top: scroll.y, width: size.x, height: size.y});
	}

	function setup(open)
	{
		["object", ie6 ? "select" : "embed"].forEach(function(tag)
		{
			Array.forEach(document.getElementsByTagName(tag), function(el)
			{
				if (open) el._slimbox = el.style.visibility;
				el.style.visibility = open ? "hidden" : el._slimbox;
			});
		});

		overlay.style.display = open ? "" : "none";

		var fn = open ? "addEvent" : "removeEvent";
		win[fn]("scroll", position)[fn]("resize", position);
		document[fn]("keydown", keyDown);
	}

	function keyDown(event)
	{
		var code = event.code;
		// Prevent default keyboard action (like navigating inside the page)
		return options.closeKeys.contains(code) ? close()
						: options.nextKeys.contains(code) ? next()
						: options.previousKeys.contains(code) ? previous()
						: false;
	}

	function previous()
	{
		return changeImage(prevImage);
	}

	function next()
	{
		return changeImage(nextImage);
	}

	function changeImage(imageIndex)
	{
		if(imageIndex >= 0)
		{
			activeImage = imageIndex;
			activeURL = images[imageIndex][0];
			prevImage = (activeImage || (options.loop ? images.length : 0)) - 1;
			nextImage = ((activeImage + 1) % images.length) || (options.loop ? 0 : -1);

			stop();
			center.className = "lbLoading";

			preload = new Image();
			preload.onload = animateBox;
			preload.src = activeURL;
		}

		return false;
	}

	function animateBox()
	{
		center.className = "";
		fxImage.set(0);
		//image.setStyles({backgroundImage: "url(" + activeURL + ")", display: "", backgroundSize: "cover"});
		image.setStyles({display: ""});
		img.setProperty("src", activeURL);

		var size = document.getSize();
		size.x = Math.round(size.x * 0.9);
		size.y = Math.round(size.y * 0.9 - 32);
		//alert(size.x + ' x ' + size.y);

		var scale = 1;
		if(preload.width > size.x)
		{
			scale = size.x / preload.width;
		}
		if(preload.height * scale > size.y)
		{
			scale = size.y / preload.height;
		}
		var width = Math.round(preload.width * scale), height = Math.round(preload.height * scale);
		image.setStyles({width: width, height: height});
		// TODO: maximum width and height also from available space
		/*sizer.setStyle("width", Math.min(preload.width, 800));
		$$(sizer, prevLink, nextLink).setStyle("height", Math.min(preload.height, 600));*/
		$$(prevLink, nextLink).setStyle("height", height);

		caption.set("html", images[activeImage][1] || "");
		number.set("html", (((images.length > 1) && options.counterText) || "").replace(/{x}/, activeImage + 1).replace(/{y}/, images.length));

		if(prevImage >= 0)preloadPrev.src = images[prevImage][0];
		if(nextImage >= 0)preloadNext.src = images[nextImage][0];

		centerWidth = image.offsetWidth;
		centerHeight = image.offsetHeight;
		var top = Math.max(0, middle - (centerHeight / 2)), check = 0, fn;
		if(center.offsetHeight != centerHeight)
		{
			check = fxResize.start({height: centerHeight, top: top});
		}
		if(center.offsetWidth != centerWidth)
		{
			check = fxResize.start({width: centerWidth, marginLeft: -centerWidth/2});
		}
		fn = function()
		{
			bottomContainer.setStyles({width: centerWidth, top: top + centerHeight, marginLeft: -centerWidth/2, visibility: "hidden", display: ""});
			fxImage.start(1);
		};
		if(check)
		{
			fxResize.chain(fn);
		}
		else
		{
			fn();
		}
	}

	function animateCaption()
	{
		if(prevImage >= 0)prevLink.style.display = "";
		if(nextImage >= 0)nextLink.style.display = "";
		fxBottom.set(-bottom.offsetHeight).start(0);
		bottomContainer.style.visibility = "";
	}

	function stop()
	{
		preload.onload = null;
		preload.src = preloadPrev.src = preloadNext.src = activeURL;
		fxResize.cancel();
		fxImage.cancel();
		fxBottom.cancel();
		$$(prevLink, nextLink, image, bottomContainer).setStyle("display", "none");
	}

	function close()
	{
		if(activeImage >= 0)
		{
			stop();
			activeImage = prevImage = nextImage = -1;
			center.style.display = "none";
			fxOverlay.cancel().chain(setup).start(0);
		}

		return false;
	}


	/*
		API
	*/

	Element.implement({
		multibox: function(_options) {
			// The processing of a single element is similar to the processing of a collection with a single element
			$$(this).multibox(_options);

			return this;
		}
	});

	Elements.implement({
		/*
			options:        Optional options object, see Slimbox.open()
		*/
		multibox: function(_options)
		{
			linkMapper = function(el)
			{
				return [el.src, el.alt];
			};

			var links = this;

			links.setStyle("cursor", "pointer").removeEvents("click").addEvent("click", function()
			{
				// Build the list of images that will be displayed
				return Multibox.open(this.getElements('img').map(linkMapper), 0, _options);
			});

			return links;
		}
	});

	return {
		open: function(_images, startImage, _options) {
			options = Object.append({
				loop: false,                            // Allows to navigate between first and last images
				overlayOpacity: 0.8,                    // 1 is opaque, 0 is completely transparent (change the color in the CSS file)
				overlayFadeDuration: 400,               // Duration of the overlay fade-in and fade-out animations (in milliseconds)
				resizeDuration: 400,                    // Duration of each of the box resize animations (in milliseconds)
				resizeTransition: false,                // false uses the mootools default transition
				initialWidth: 250,                      // Initial width of the box (in pixels)
				initialHeight: 250,                     // Initial height of the box (in pixels)
				imageFadeDuration: 400,                 // Duration of the image fade-in animation (in milliseconds)
				captionAnimationDuration: 400,          // Duration of the caption animation (in milliseconds)
				counterText: "Image {x} of {y}",        // Translate or change as you wish, or set it to false to disable counter text for image groups
				closeKeys: [27, 88, 67],                // Array of keycodes to close Slimbox, default: Esc (27), 'x' (88), 'c' (67)
				previousKeys: [37, 80],                 // Array of keycodes to navigate to the previous image, default: Left arrow (37), 'p' (80)
				nextKeys: [39, 78]                      // Array of keycodes to navigate to the next image, default: Right arrow (39), 'n' (78)
			}, _options || {});

			// Setup effects
			fxOverlay = new Fx.Tween(overlay, {property: "opacity", duration: options.overlayFadeDuration});
			fxResize = new Fx.Morph(center, Object.append({duration: options.resizeDuration, link: "chain"}, options.resizeTransition ? {transition: options.resizeTransition} : {}));
			fxImage = new Fx.Tween(img, {property: "opacity", duration: options.imageFadeDuration, onComplete: animateCaption});
			fxBottom = new Fx.Tween(bottom, {property: "margin-top", duration: options.captionAnimationDuration});

			// The function is called for a single image, with URL and Title as first two arguments
			if (typeof _images == "string") {
				_images = [[_images, startImage]];
				startImage = 0;
			}

			middle = win.getScrollTop() + (win.getHeight() / 2);
			centerWidth = options.initialWidth;
			centerHeight = options.initialHeight;
			center.setStyles({top: Math.max(0, middle - (centerHeight / 2)), width: centerWidth, height: centerHeight, marginLeft: -centerWidth/2, display: ""});
			compatibleOverlay = ie6 || (overlay.currentStyle && (overlay.currentStyle.position != "fixed"));
			if (compatibleOverlay) overlay.style.position = "absolute";
			fxOverlay.set(0).start(options.overlayOpacity);
			position();
			setup(1);

			images = _images;
			options.loop = options.loop && (images.length > 1);
			return changeImage(startImage);
		}
	};
})();

// AUTOLOAD CODE BLOCK (MAY BE CHANGED OR REMOVED)
window.addEvent('domready', function(){
	if(!/android|iphone|ipod|series60|symbian|windows ce|blackberry/i.test(navigator.userAgent))
	{
		$$(".multibox").multibox({counterText: "Bild {x} von {y}"});
	};
});
