/**
 * 
 * @author André Hoendgen <hoendgen@engine-productions.de>
 * @copyright Engine-Productions GmbH 2011 * 
 * 
 */

(function($){
	$.epslider = function(el, options){
		// To avoid scope issues, use 'base' instead of 'this'
		// to reference this class from internal events and functions.
		var base = this;
		var $$ = null;
        
		if(options == "destroy") {
			$$.unbind("epslider.after");
			$$.unbind("epslider.before");
			return null;
		}
		
		options = $.extend({},$.epslider.defaultOptions, options);
		
		if(options.showStats) {
			var stats = new Stats();

			// Align top-left
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.left = '0px';
			stats.domElement.style.top = '0px';

			document.body.appendChild(stats.domElement);
		}
		
		// Access to jQuery and DOM versions of element
		base.$el = $(el);
		base.el = el;
		$$ = base.$el;
        
		// Add a reverse reference to the DOM object
		base.$el.data("epslider", base);
        
		base.init = function(){
			base.options = options;
            
			base.stopAnimationDelay = new Array();
			
			//add events
			$$.bind("epslider.after", base.options.after);
			$$.bind("epslider.before", base.options.before);
			
			//select slides
			
			$$.find(base.options.slideContainer).each(function(key, item) {
				var $$ = $(item);
				
				if($$.find(options.slide).size() <= 0) {
					$$.remove();
				}
			})
			
			base.slideContainer = $$.find(base.options.slideContainer);
			base.currentContainer = 0;
			base.prevContainer = base.currentContainer;
			base.counterContainer = base.slideContainer.size();
			
			
			if(options.pagination) {
				var pagination = document.createElement("ul");
				var li = null;
				base.slideContainer.each(function(i) {
					
					li = document.createElement("li");
					li.innerHTML = (i+1);
					
					$(li).click(function() {
						base.showSlide(i);
					})
					
					pagination.appendChild(li);
					li = null;
				});
				
				$(pagination).addClass("sliderPagination").insertBefore($$);
				base.pagination = $(pagination);
			}
			
			//add z-index
			base.slideContainer.each(function(key, item) {
				$(item).css("z-index", (base.counterContainer-key));
			})
			
			base.logic(base.options);
			
		//			if(base.options.startCenter) {
		//				base.centerSlides();
		//			}
			
		};
		
		base.centerSlides = function() {
			$$.find(options.slideContainer).each(function(key, item) {
					
				var $$ = $(item);

				var height = $$.height();
				var width = $$.width();
					
				$$ = $$.find(options.slide);
					
				height = height - $$.height();
				width = width - $$.width();
					
				height = height/2;
				width = width/2;
					
				$$.css({
					left: width,
					top: height
				});
				
			});
		}
		
		base.logic = function() {
			
			var options = base.options;
			
			var cont = base.slideContainer.eq(base.currentContainer);
			var slide = cont.find(options.slide);
			var img = null;
			base.fallback = false;
			
			if(slide.size() > 1) {
				img = cont.find(options.slide + " .fallback").get(0);		
				base.fallback = slide.not(".fallback");
			} else {
				img = slide.get(0);
			}
			
			if(!options.showIosPlayButton) {
				base.fallback = false;
			}			
			
			var ani = null;
			
			if(options.pagination !== false) {
				base.pagination.find("li").removeClass("current");
				base.pagination.find("li").eq(base.currentContainer).addClass("current");
			}
			
			base.slideContainer.hide().eq(base.prevContainer).show();
			cont.fadeIn();
			
			if(undefined == options.animations[base.currentContainer]) {
				ani = options.animations[0];
			} else {
				ani = options.animations[base.currentContainer];
			}
			
			if(options.randomAnimation) {
				ani = base.shuffle(options.animations);
				ani = ani[0];
			}
			
			if(typeof ani === "function") {
				ani(base);
				return;
			}
			
			if(undefined == img) {
				base.next();
				return;
			}
			
			base.cont = cont;
			base.slide = slide;
			
			if(img.tagName == "IMG") {
				
				if(!img.complete) {
					img.onload = function() {
						base.animateImage(ani, cont, img, slide);
					}
				} else {
					base.animateImage(ani, cont, img, slide);
				}
				
			} else if(img.tagName == "VIDEO") {
				base.animateVideo(img, slide, cont)
			}
			
			base.$el.data("epslider", base);
			
		}
		
		base.animateVideo = function(video, slide, cont) {
			$(cont).find(".fallbackButton").remove();
			
			var $$ = $(video);
			
			var fadeStarted = false;
			
			base.$el.trigger("epslider.before");
			
			
			base.animationStart = base.time();
			
			base.stopped = false;
					
			base.stopCurrent = function() {
				video.pause();
				video.currentTime = 0;
				noDraw = true;
				return;
			}	
							
			$$.bind("timeupdate", function timeupdate(e) {
				
				if(base.stopped) {
					video.pause();
					video.currentTime = 0;
					base.next();
					return;
				}
				
				if(fadeStarted) return;
				
				if(undefined != stats) {
					stats.update();
				}
				
				var cur = Math.round(this.currentTime);
				var dur = Math.round(this.duration);
				var fadeStart = dur - 2;
				
				
				if(cur >= fadeStart && fadeStart > 0) {
					base.prevContainer = base.currentContainer;
					if(base.currentContainer == (base.counterContainer-1)) {
						base.currentContainer = -1;
						
						if(!options.restart) {
							return;
						}
					}
				
					if(!fadeStarted) {
						if(base.options.onDraw) {
							base.options.onDraw(base, true);
						}
					}
				
					if(options.autoplay) {
						base.next();
					}
					
					fadeStarted = true;
				}
			});
			
			video.play();
		}
		
		base.animateImage = function(ani, cont, img, slide) {
			
			var from = ani.from;
			var to = ani.to;
			
			$(img).show();
			
			$(cont).find("canvas").remove();
			$(cont).find(".fallbackButton").remove();
			
			if($(img).hasClass("fallback") && base.fallback !== false) {
				$("<div>").addClass("fallbackButton").click(function(e) {
					
					e.preventDefault();
					
					$("#slideshow").data("epslider").stop();
					
					
					$(cont).find("canvas").fadeOut("slow");
					$(img).fadeOut("slow");
					base.fallback.fadeIn("slow");
					$("#slideshow").data("epslider").animateVideo(base.fallback.get(0), slide, cont);
						
				}).appendTo($(img).parent());
			}
			
			if(base.isiOS() || base.isWebkit()) {
				base.animateImageCss(ani, cont, img, slide);
				return;
			}
			
			if($.browser.msie) {
				base.animateImageIE(ani, cont, img, slide);
				return;
			}
			
			var can = document.createElement("canvas");
			var cswitch = can.getContext;
			
			if(!cswitch) {
				base.animateImageNoCanvas(ani, cont, img, slide);
				return;
			}
			
			can.width = cont.width();
			can.height = cont.height();
			
			var con = can.getContext("2d");
			
			
			
			var sxBase = ((img.width - can.width)/100);
			var syBase = ((img.height - can.height)/100);
			
			var txBase = ((img.width - can.width)/100);
			var tyBase = ((img.height - can.height)/100);
			
			var sx = sxBase * from[0];
			var sy = syBase * from[1];
			
			var sh = img.height;
			var sw = img.width;
			
			var tx = txBase * to[0];
			var ty = tyBase * to[1];
			
			
			if(ty <= 0) {
				ty = 1;
			}
			if(tx <= 0) {
				tx = 1;
			}
			
			sx = sx*-1;
			sy = sy*-1;
			
			var scale = (from[2]/100);
			var tscale = (to[2]/100);
			
			$(can).insertAfter(slide);
			slide.hide();
			
			$$.trigger("epslider.before");
			
			base.stopped = false;
			
			var imgHeight = img.height;
			var imgWidth = img.width;
			
			base.animationStart = base.time();
			var vars = $.extend($('<div>')[0], {
				sx: sx,
				sy: sy,
				sw: sw,
				sh: sh,
				scale: scale,
				customAnimate: true,
				updated: true
			}, {
				easing: "linear"
			})
			
			$(vars).animate({
				sx: tx, 
				sy: ty,
				scale: tscale
			}, {
				duration: options.duration,
				easing: "linear",
				complete: function() {
					
					if(!options.restart) {
						return;
					}
					if(options.autoplay) {
						base.next();
					}
				}
			});
			
			var contWidth = can.width;
			var contHeight = can.height;
			
			var cache = document.createElement("canvas");
			cache.width = img.width;
			cache.height = img.height;
			var concache = cache.getContext("2d");
			
			var lastScale = 0;
			function drawImage() {
				
				if(options.onDraw) {
					options.onDraw(base);
				}
				
				if (!vars.updated) return;
				vars.updated = false;
				
				if(vars.scale != lastScale) {
					var dh = imgHeight * vars.scale;
					var dw = imgWidth * vars.scale;
				
					concache.drawImage(img, 0, 0, dw, dh);
				}
				
				con.drawImage(cache, vars.sx, vars.sy, contWidth, contHeight, 0, 0, contWidth, contHeight);
				
				if(options.showStats) {
					stats.update();
				}
				
				base.vars = vars;
			}
			
			base.stopAnimationDelay[base.currentContainer] = false;
			var curSlide = base.currentContainer;
			
			
			if(!undefined == base.stopAnimationDelay[curSlide]) {
				base.stopAnimationDelay[curSlide] = false;
			}
			
			function animate() {
				if(!base.stopped && !base.stopAnimationDelay[curSlide]) {
					requestAnimationFrame(animate);
					drawImage();
				} else {
					$(vars).stop(true);
				}
			}
			
			animate();
			
			base.stopCurrent = function() {
				$(base.vars).stop(true);
			}
		}
		
		base.animateImageCss = function(ani, cont, img, slide) {
			
			
			var from = ani.from;
			var to = ani.to;
			
			var can = $(cont);
			
			var sxBase = ((img.width - can.width())/100);
			var syBase = ((img.height - can.height())/100);
			
			var txBase = ((img.width - can.width())/100);
			var tyBase = ((img.height - can.height())/100);
			
			var sx = sxBase * from[0];
			var sy = syBase * from[1];
			
			var sh = img.height;
			var sw = img.width;
			
			var tx = txBase * to[0];
			var ty = tyBase * to[1];
			
			if(ty <= 0) {
				ty = 1;
			}
			if(tx <= 0) {
				tx = 1;
			}
			
			
			var scale = (from[2]/100);
			var tscale = (to[2]/100);
			
			sx = sx*-1;
			sy = sy*-1;
			
			var prefix = "-moz-";
			
			if(base.isiOS() || base.isWebkit()) {
				prefix = "-webkit-";
			}
			
			var transform = prefix + "transform";
			var transformOrigin = prefix + "transform-origin";
			
			slide.css("image-rendering", "optimizequality")
			.css(transform, " translate3d(" + sx + "px, " + sy + "px, 0) scale(" + scale + ")")
			.css(transformOrigin, "0 0");
		
			if(sx < tx) {
				tx = tx * -1;
			}
			if(sy < ty) {
				ty = ty * -1;
			}
			
			var vars = $.extend($('<div>')[0], {
				sx: sx,
				sy: sy,
				sw: sw,
				sh: sh,
				scale: scale,
				customAnimate: true,
				updated: true
			});
			
			
			base.animationStart = base.time();
			$$.trigger("epslider.before");
			$(vars).animate({
				sx: tx, 
				sy: ty,
				scale: tscale
			}, {
				duration: options.duration,
				easing: "linear",
				complete: function() {
				
					if(!options.restart) {
						return;
					}
						
					if(options.autoplay) {
						base.next();
					}
				}
			});

			base.stopped = false;
			
			function drawImage() {
				
				if(options.onDraw) {
					options.onDraw(base);
				}
				
				if (!vars.updated) return;
				vars.updated = false;
				
				slide.css(prefix + "transform", " translate3d(" + vars.sx + "px, " + vars.sy + "px, 0) scale(" + vars.scale + ")")
				
				if(options.showStats) {
					stats.update();
				}
			}
			
			base.stopAnimationDelay[base.currentContainer] = false;
			var curSlide = base.currentContainer;
			
			
			if(!undefined == base.stopAnimationDelay[curSlide]) {
				base.stopAnimationDelay[curSlide] = false;
			}
			
			function animate() {
				if(!base.stopped && !base.stopAnimationDelay[curSlide]) {
					requestAnimationFrame(animate);
					drawImage();
				} else {
					$(vars).stop(true);
					base.stopAnimationDelay[curSlide] = false;
				}
			}
			
			animate();
			
			base.stopCurrent = function() {
				$(base.vars).stop(true);
			}
		}
		
		base.animateImageIE = function(ani, cont, img, slide) {
			
			
			var from = ani.from;
			var to = ani.to;
			
			var can = $(cont);
			
			var sxBase = ((img.width - can.width())/100);
			var syBase = ((img.height - can.height())/100);
			
			var txBase = ((img.width - can.width())/100);
			var tyBase = ((img.height - can.height())/100);
			
			var sx = sxBase * from[0];
			var sy = syBase * from[1];
			
			var sh = img.height;
			var sw = img.width;
			
			var tx = txBase * to[0];
			var ty = tyBase * to[1];
			
			if(ty <= 0) {
				ty = 1;
			}
			if(tx <= 0) {
				tx = 1;
			}
			
			
			var scale = (from[2]/100);
			var tscale = (to[2]/100);
			
			sx = sx*-1;
			sy = sy*-1;
			
			$(img).css("image-rendering", "optimizeQuality").css("-ms-interpolation-mode", "bicubic");
		
			if(sx < tx) {
				tx = tx * -1;
			}
			if(sy < ty) {
				ty = ty * -1;
			}
			
			var vars = $.extend($('<div>')[0], {
				sx: sx,
				sy: sy,
				sw: sw,
				sh: sh,
				scale: scale,
				customAnimate: true,
				updated: true
			});
			
			
			base.animationStart = base.time();
			$$.trigger("epslider.before");
			$(vars).animate({
				sx: tx, 
				sy: ty,
				scale: tscale
			}, {
				duration: options.duration,
				easing: "linear",
				complete: function() {
				
					if(!options.restart) {
						return;
					}
						
					if(options.autoplay) {
						base.next();
					}
				}
			});

			base.stopped = false;
			
			function drawImage() {
				
				if(options.onDraw) {
					options.onDraw(base);
				}
				
				if (!vars.updated) return;
				vars.updated = false;
				
				slide.css("filter", 'progid:DXImageTransform.Microsoft.Matrix(FilterType="bilinear",M11=' + vars.scale + ',M12=0,M21=0,M22=' + vars.scale + ',Dx=' + vars.sx + ',Dy=' + vars.sy + ')');
				
				if(options.showStats) {
					stats.update();
				}
			}
			
			base.stopAnimationDelay[base.currentContainer] = false;
			var curSlide = base.currentContainer;
			
			
			if(!undefined == base.stopAnimationDelay[curSlide]) {
				base.stopAnimationDelay[curSlide] = false;
			}
			
			function animate() {
				if(!base.stopped && !base.stopAnimationDelay[curSlide]) {
					requestAnimationFrame(animate);
					drawImage();
				} else {
					$(vars).stop(true);
					base.stopAnimationDelay[curSlide] = false;
				}
			}
			
			animate();
			
			base.stopCurrent = function() {
				$(base.vars).stop(true);
			}
		}
		
		base.animateImageNoCanvas = function(ani, cont, img, slide) {
			
			$(img).css("image-rendering", "optimizeQuality").css("-ms-interpolation-mode", "bicubic");
			
			var from = ani.from;
			var to = ani.to;
			
			var can = $(cont);
			
			var sxBase = ((img.width - can.width())/100);
			var syBase = ((img.height - can.height())/100);
			
			var txBase = ((img.width - can.width())/100);
			var tyBase = ((img.height - can.height())/100);
			
			var sx = sxBase * from[0];
			var sy = syBase * from[1];
			
			var sh = img.height;
			var sw = img.width;
			
			var tx = txBase * to[0];
			var ty = tyBase * to[1];
			
			if(ty <= 0) {
				ty = 1;
			}
			if(tx <= 0) {
				tx = 1;
			}
			
			var scale = (from[2]/100);
			var tscale = (to[2]/100);
			
			var dw = sw * scale;
			var dh = sh * scale;
			
			sx = sx*-1;
			sy = sy*-1;
			
			slide.css({
				left: sx + "px",
				top: sy + "px",
				width: sw + "px",
				height: sh + "px"
			});
			
			if(sx < tx) {
				tx = tx * -1;
			}
			if(sy < ty) {
				ty = ty * -1;
			}
			
			var vars = $.extend($('<div>')[0], {
				sx: sx,
				sy: sy,
				sw: sw,
				sh: sh,
				scale: scale,
				customAnimate: true,
				updated: true
			});
			
			
			base.animationStart = base.time();
			$(vars).animate({
				sx: tx, 
				sy: ty,
				scale: tscale
			}, {
				duration: options.duration,
				easing: "linear",
				complete: function() {
				
					if(!options.restart) {
						return;
					}
						
					if(options.autoplay) {
						base.next();
					}
				}
			});
			
			$$.trigger("epslider.before");

			base.stopped = false;
			
			function drawImage() {
				
				if(options.onDraw) {
					options.onDraw(base);
				}
				
				if (!vars.updated) return;
				vars.updated = false;
				
				
				var ttx = vars.sx;
				var tty = vars.sy;
				
				var dw = sw * vars.scale;
				var dh = sh * vars.scale;
				
			
				slide.css({
					left: ttx + "px",
					top: tty + "px",
					width: dw + "px",
					height: dh + "px"
				});
				
				
				if(options.showStats) {
					stats.update();
				}
			}
			
			function animate() {
				if(!base.stopped) {
					requestAnimationFrame(animate);
					drawImage();
				} else {
					$(vars).stop(true);
				}
			}
			
			animate();
			
			base.stopCurrent = function() {
				$(base.vars).stop(true);
			}
		}
		
		base.isVideoSlide = function() {
			
			var img = base.slideContainer.eq(base.currentContainer).find(base.options.slide).get(0);
			
			if(undefined == img) {
				return false;
			}
			
			if(img.tagName == "VIDEO") {
				return true;
			}
			
			return false;
		}
		
		base.stop = function() {
			
			base.stopped = true;
			base.stopAnimationDelay[base.currentContainer] = true;
			
			try {
				base.stopCurrent();
			} catch(e) {}
		}
		
		base.time = function() {
			return Math.floor(new Date().getTime() / 1000);
		}
		
		base.shuffle = function(inputArr) {
			// http://kevin.vanzonneveld.net
			// +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
			// +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
			// +    revised by: Brett Zamir (http://brett-zamir.me)
			// +   improved by: Brett Zamir (http://brett-zamir.me)
			// %        note 1: This function deviates from PHP in returning a copy of the array instead
			// %        note 1: of acting by reference and returning true; this was necessary because
			// %        note 1: IE does not allow deleting and re-adding of properties without caching
			// %        note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
			// %        note 1: get the PHP behavior, but use this only if you are in an environment
			// %        note 1: such as Firefox extensions where for-in iteration order is fixed and true
			// %        note 1: property deletion is supported. Note that we intend to implement the PHP
			// %        note 1: behavior by default if IE ever does allow it; only gives shallow copy since
			// %        note 1: is by reference in PHP anyways
			// *     example 1: ini_set('phpjs.strictForIn', true);
			// *     example 1: shuffle({5:'a', 2:'3', 3:'c', 4:5, 'q':5});
			// *     returns 1: {5:'a', 4:5, 'q':5, 3:'c', 2:'3'}
			// *     example 2: ini_set('phpjs.strictForIn', true);
			// *     example 2: var data = {5:'a', 2:'3', 3:'c', 4:5, 'q':5};
			// *     example 2: shuffle(data);
			// *     results 2: {5:'a', 'q':5, 3:'c', 2:'3', 4:5}
			// *     returns 2: true
			var valArr = [],
			k = '',
			i = 0,
			strictForIn = false,
			populateArr = [];

			for (k in inputArr) { // Get key and value arrays
				if (inputArr.hasOwnProperty(k)) {
					valArr.push(inputArr[k]);
					if (strictForIn) {
						delete inputArr[k];
					}
				}
			}
			valArr.sort(function () {
				return 0.5 - Math.random();
			});

			// BEGIN REDUNDANT
			this.php_js = this.php_js || {};
			this.php_js.ini = this.php_js.ini || {};
			// END REDUNDANT
			strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
			populateArr = strictForIn ? inputArr : populateArr;

			for (i = 0; i < valArr.length; i++) { // Repopulate the old array
				populateArr[i] = valArr[i];
			}

			return strictForIn || populateArr;
		}

		
		base.next = function(stopit) {
				
			var curCont = base.currentContainer;
			base.prevContainer = base.currentContainer;
			if(base.currentContainer == (base.counterContainer-1)) {
				base.currentContainer = -1;
			}
			
			if(undefined == stopit || base.isVideoSlide()) {
				base.stop();
			}
				
			$$.trigger("epslider.after");
				
			if(undefined != base.cont) {
				base.cont.fadeOut("slow", function() {
					base.stopAnimationDelay[curCont] = true;
				});
			} else {
				base.stopAnimationDelay[curCont] = true
			}
			
			base.currentContainer++;
			
			base.logic();
		}
		
		base.showSlide = function(slide) {
			
			if(slide < 0 || slide > base.counterContainer || slide == base.currentContainer) {
				return;
			}
			
			$$.trigger("epslider.after");
				
			var curCont = base.currentContainer;
			
			if(undefined != base.cont && slide != base.currentContainer) {
				base.cont.fadeOut("slow", function() {
					base.stopAnimationDelay[curCont] = true;
				});
			} else {
				base.stopAnimationDelay[curCont] = true
			}
			
			if(base.isVideoSlide()) {
				base.stop();
			}
			
			base.prevContainer = base.currentContainer;
			base.currentContainer = slide;
			
			if(base.isVideoSlide()) {
				base.stop();
			}
			
			base.logic();
		}
		
		base.isiOS = function() {
			
			return (
				//Detect iPhone
				(navigator.platform.indexOf("iPhone") != -1) ||
				//Detect iPod
				(navigator.platform.indexOf("iPod") != -1) ||
				//Detect iPad
				(navigator.platform.indexOf("iPad") != -1)
				);
		}
		
		base.isWebkit = function() {
			return Boolean($.browser.webkit);
		}
		
		// Run initializer
		base.init();		
	};
    
	$.epslider.defaultOptions = {
		animations: null,
		duration: 3000,
		after: function(){},
		before: function(){},
		slide: "*:first",
		slideContainer: " > *",
		restart: true,
		autoplay: true,
		showIosPlayButton: false,
		pagination: false,
		randomAnimation: false,
		onDraw: false
	};
    
	$.fn.epslider = function(options){
		return this.each(function(){
			(new $.epslider(this, options));
		});
	};
	    
})(jQuery);

function rand( min, max ) {
	if( min > max ) {
		return( -1 );
	}
	if( min == max ) {
		return( min );
	}
 
	return( min + parseInt( Math.random() * ( max-min+1 ) ) );
}


if ( !window.requestAnimationFrame ) {
	window.requestAnimationFrame = ( function() {
		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
			window.setTimeout( callback, 1000 / 500 );
		};
	} )();
}


			
var $_fx_step_default = $.fx.step._default;
$.fx.step._default = function (fx) {
	if (!fx.elem.customAnimate) return $_fx_step_default(fx);
	fx.elem[fx.prop] = fx.now;
	fx.elem.updated = true;
};
