;(function($) {
	// Enable strict mode
	"use strict";
	
	$.fn.userRandomImageRotation = function(options)
	{
		var run = function(container, config) 
		{
			var app = {};
			
			app._randomiseArray = function(array) 
			{
				var currentIndex = array.length, temporaryValue, randomIndex;

				// While there remain elements to shuffle...
				while (0 !== currentIndex) {
				
					// Pick a remaining element...
					randomIndex = Math.floor(Math.random() * currentIndex);
					currentIndex -= 1;

					// And swap it with the current element.
					temporaryValue = array[currentIndex];
					array[currentIndex] = array[randomIndex];
					array[randomIndex] = temporaryValue;
				}
				return array;
			};
			
			app._init = function(container, config)
			{
				app.el = {};
				app.cache = {};
				
				// init options
				app.cfg = config;
				app.el.container = $(container);
				app.el.items = app.el.container.find("." + app.cfg.containerClass).addClass(app.cfg.imageNotLoadedClass);
				
				app.cache.allLoaded = false;
			};
			
			app._preloadNext = function() 
			{
				if (app.cache.allLoaded) return;
				
				// get not loaded image element container items
				var notLoadedItems = app.el.items.filter("." + app.cfg.imageNotLoadedClass);

				if (!notLoadedItems.length) {
					app.cache.allLoaded = true;
					return;
				}
				
				var item = notLoadedItems.first();
				
				if (item.length) {
					app._transformCandidateToImage(item);
				} 
			};
			
			/**
			 * @param object item container div for image and description
			 */
			app._transformCandidateToImage = function(item) 
			{
				// check if image is already loaded
				if (item.hasClass(app.cfg.imageLoadedClass)) return item;
				
				// find image candidate, check existence
				var imageCandidate = item.find("." + app.cfg.candidateClass);
				if (!imageCandidate.length) return item;
				
				imageCandidate.removeClass(app.cfg.candidateClass);
				
				// insert empty image
				imageCandidate.after('<img class="'+ app.cfg.temporarySelectorClass +'">');
				
				// get image object
				var image = imageCandidate.next("img." + app.cfg.temporarySelectorClass);
				
				// fill image with life
				// copy classes, remove unused and temporary classes
				image.addClass(imageCandidate.attr("class")).removeClass(app.cfg.candidateClass).removeClass(app.cfg.temporarySelectorClass);
				
				// copy other attributes
				image.attr({
					"srcset": imageCandidate.attr("data-srcset"),
					"sizes": imageCandidate.attr("data-sizes"),
					"width": imageCandidate.attr("data-width"),
					"height": imageCandidate.attr("data-height"),
					"src": imageCandidate.attr("data-src"),
					"alt": imageCandidate.attr("data-alt")
				});
								
				imageCandidate.remove();
				item.fadeOut(0);
				item.removeClass(app.cfg.imageNotLoadedClass).addClass(app.cfg.imageLoadedClass);
				window.picturefill();
				
				return item;
			};
			
			app._change = function() {
				
				var active = app.el.items.filter("." + app.cfg.activeClass);
				var nextActive = active.next("." + app.cfg.containerClass);
				
				if (!nextActive.length) nextActive = app.el.items.first();
				
				// effect chain
				nextActive.css("z-index", 0).fadeIn(0);
				
				active.fadeOut(app.cfg.effectTime, function() {
					$(this).removeClass(app.cfg.activeClass);
					nextActive.addClass(app.cfg.activeClass).css("z-index", 1);
				});
				app._preloadNext();
				app.timeout = setTimeout(function(){ app._change(); }, app.cfg.displayTime);
			};
			
			// CODE //
			app._init(container, config);
			
			// none or only one item
			if (!app.el.items.length) return;
			
			// get shuffled key array
			var keys = [];
			for (var i=0; i < app.el.items.length; i++) {
				keys.push(i);
			}
			keys = app._randomiseArray(keys);
			
			// reorder candidate items
			for (i=0; i < keys.length; i++) {
				var key = keys[i];
				var $item = $(app.el.items[key]).detach();
				app.el.container.prepend($item);
			}
			
			// reset items
			app.el.items = app.el.container.find("." + app.cfg.containerClass);
			
			// preload images
			for (var i=0; i <= app.cfg.preloadCount; i++) {
				var $item = app._transformCandidateToImage($(app.el.items[i]));
				
				// make a copy of first image as a placeholder (invisible, but space consuming).
				if (i == 0) {
					var $placeholder = $item.clone();
					$placeholder.attr({
						"class": "rotation-image-placeholder",
						"style":"visibility:hidden;"
					});
					
					app.el.container.prepend($placeholder);
				}
			}
//			return;
			// start animation
			setTimeout(function(){
				app.el.items.first().fadeIn(app.cfg.effectTimeFirst).addClass(app.cfg.activeClass).css("z-index", 1);
				app.cache.timeout = setTimeout(function(){ app._change(); }, app.cfg.displayTimeFirst);
			}, app.cfg.startDelay);
			
			
		};
		
		// Default options.
        var config = $.extend({
        	containerClass: "imagerotation-image-container",
        	candidateClass: "image-candidate",
        	activeClass: "image-active",
        	temporarySelectorClass: "new-image",
        	imageLoadedClass: "image-loaded",
        	imageNotLoadedClass: "image-not-loaded",
        	preloadCount: 1,
        	startDelay: 350,
        	displayTimeFirst: 1500,
			displayTime: 3000,
			effectTimeFirst: 3500,
			effectTime: 350
        }, options );
		
		return this.each(function() {
			run(this, config);
	    });
		
	};

})(jQuery);
