if (typeof($.fn.w2dplugincarousel)=='undefined') {

	(function($){
		/*
		 * Creates a 3D-Image caousel
		 */
		$.fn.w2dplugincarousel = function(images, options){
			this.angle = 0;
			this.sourceangle = 0;
			this.destangle = 0;
			this.offset = 0;
			this.speed = 0;
			this.controller = 0;
			this.elements = [];
			this.current = 0;
			this.rolling = false;
			this.zoom = false;
			
			var context;
			
			this.settings = {
				scalex : 0.65,
				scaley : 0.4,
				hoverzoom: 1.5,
				autospin: 3,
				stagewidth: 800,
				stageheight: 400
			}
			
			/*
			 * Places Images correctly
			 */
			this.placeimages = function(){
				var segmentangel = 360 / this.elements.length;
				var stagecenterx = this.settings.stagewidth / 2;
				var stagecentery = (this.settings.stageheight / 2) - 30;
				var radiusx = stagecenterx * this.settings.scalex;
				var radiusy = stagecentery * this.settings.scaley;
				
				for (var i = 0; i < this.elements.length; i++) {
					var arc = (this.angle + i * segmentangel) / 180 * Math.PI;
					
					var x = stagecenterx + radiusx * Math.sin(arc);
					var y = stagecentery + radiusy * Math.cos(arc);
					
					var scale = 0.60 + (1 + Math.cos(arc)) / 2 * 0.40;
					var zindex = (1 + Math.cos(arc)) * 499;
					
					var h = this.elements[i].height * scale;
					var w = this.elements[i].width * scale;
					
					var cssleft = Math.round(x - w / 2) + 'px';
					var csstop = Math.round(y - h / 2) + 'px';
					var cssheight = Math.round(h) + 'px';
					var csswidth = Math.round(w) + 'px';
					var csszindex = Math.round(zindex);
					
					$(this.elements[i].node).css({
						left: cssleft,
						top: csstop,
						height: cssheight,
						width: csswidth,
						zIndex: csszindex
					});
					
					var csstop = Math.round(y - h / 2) + Math.round(h)- 1 + 'px';
					
					$(this.elements[i].reflectionnode).css({
						left: cssleft,
						top: csstop,
						width: csswidth,
						zIndex: csszindex - 1
					});
					
				}
			}
			
			/*
			 * Handles click on images
			 */
			this.handleclick = function(){
				this.context.stop();
				if (this.context.current == this.carouselindex) {
					if (this.context.elements[this.carouselindex].url!="") {
						window.location = this.context.elements[this.carouselindex].url;
					}
				}
				else {
					this.context.rotateto(this.carouselindex);
				}
			}
			
			/*
			 * Handles mouseover on images
			 */
			this.handlemouseover = function(){
				this.context.stop();
				if (!this.context.rolling) {
					if (this.context.current == this.carouselindex) {
						this.zoom = true;
						this.context.resizeelement(this.carouselindex, this.context.settings.hoverzoom);
					}
				}
			}
			
			/*
			 * Handles mouseout on images
			 */
			this.handlemouseout = function(){
				this.context.stop();
				if (!this.context.rolling) {
					if (this.context.current == this.carouselindex) {
						if (this.zoom) {
							this.context.resizeelement(this.carouselindex, 1);
							this.zoom = false;
						}
					}
				}
			}
			
			/*
			 * Resizes an element animated
			 */
			this.resizeelement = function(index, factor){
				var segmentangel = 360 / this.elements.length;

				var stagecenterx = this.settings.stagewidth / 2;
				var stagecentery = (this.settings.stageheight / 2) - 30;
				var radiusx = stagecenterx * this.settings.scalex;
				var radiusy = stagecentery * this.settings.scaley;
				
				var arc = (this.angle + index * segmentangel) / 180 * Math.PI;
					
				var x = stagecenterx + radiusx * Math.sin(arc);
				var y = stagecentery + radiusy * Math.cos(arc);
								
				var h = this.elements[index].height * factor;
				var w = this.elements[index].width * factor;
				
				var cssleft = Math.round(x - w / 2) + 'px';
				var csstop = Math.round(y - h / 2) + 'px';
				var cssheight = Math.round(h) + 'px';
				var csswidth = Math.round(w) + 'px';
				
				$(this.elements[index].node).stop().animate({
					left: cssleft,
					top: csstop,
					height: cssheight,
					width: csswidth
				}, {
					duration: 200,
					easing: 'w2dplugincarouseleasing'
				});
			}
			
			/*
			 * Creates the reflection effect
			 */
			this.drawreflection = function(){
				var element = this.context.elements[this.carouselindex];
				
				var cntx = element.reflectionnode.getContext("2d");
				cntx.save();
				cntx.translate(0, element.height - 1);
				cntx.scale(1, -1);
				cntx.drawImage(element.node, 0, 0, element.width, element.height);
				cntx.restore();
				cntx.globalCompositeOperation = "destination-out";
				
				var gradient = cntx.createLinearGradient(0, 0, 0, 30);
				gradient.addColorStop(0, "rgba(255, 255, 255, 0.6)");
				gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
				
				cntx.fillStyle = gradient;
				cntx.fillRect(0, 0, element.width, 30);
			}
			
			/*
			 * Creates the images
			 */
			this.createimages = function(images){
				var context = this;
				
				this.elements = images;
				
				for (var i = 0; i < images.length; i++) {
					var image = document.createElement('img');
					image.style.width = images[i].width + 'px';
					image.style.height = images[i].height + 'px';
					image.style.position = 'absolute';
					image.style.cursor = 'pointer';
					image.carouselindex = i;
					image.context = context;
					image.onclick = this.handleclick;
					image.onmouseover = this.handlemouseover;
					image.onmouseout = this.handlemouseout;
					$(this).append(image);
					this.elements[i].node = image;
					
					if ($.browser.msie && $.browser.version<9) {
						var finishy = 30 / images[i].height * 100
						var reflection = document.createElement('img');
						reflection.style.position = 'absolute';
						reflection.style.width = images[i].width + 'px';
						reflection.style.height = images[i].height + 'px';
						reflection.src = images[i].src;
						reflection.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity=60, style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=' + finishy + ')';
						$(this).append(reflection);
						this.elements[i].reflectionnode = reflection;
					} else {
						var reflection = document.createElement('canvas');
						reflection.style.position = 'absolute';
						reflection.width = images[i].width;
						reflection.height = 30;
						
						$(this).append(reflection);
						this.elements[i].reflectionnode = reflection;
						$(image).load(this.drawreflection);
					}
					image.src = images[i].src;
				}
			}
			
			/*
			 * Calculates the difference of two angles
			 */
			this.anglediff = function(anglea, angleb){
				var difference = angleb - anglea;
				while (difference < -180) 
					difference += 360;
				while (difference > 180) 
					difference -= 360;
				return difference;
			}
			
			/*
			 * Performs the rotation
			 */
			this.rotate = function(){
				var context = this;
				
				var destoffset = this.anglediff(this.sourceangle, this.destangle);
				
				this.offset += 0.1;
				
				if (this.offset >= 2) {
					this.angle = this.destangle;
				} else {
					this.angle = Math.round(this.sourceangle + ((this.offset <= 1) ? Math.pow(this.offset, 2) : (2 - Math.pow((2 - this.offset), 2))) * destoffset / 2);
				}
				
				this.placeimages();
				
				if (this.offset <= 2) {
					setTimeout(function(){
						context.rotate();
					}, 30)
				} else {
					this.rolling = false;
				}
			}
			
			/*
			 * Brings a certaint index to front
			 */
			this.rotateto = function(index){
				if (!this.rolling) {
					if (this.current != index) {
						this.rolling = true;
						this.current = index;
						this.destangle = 360 - index / this.elements.length * 360;
						this.sourceangle = this.angle;
						this.speed = 0;
						this.offset = 0;
						this.rotate();
					}
				}
				
			}
									
			/*
			 * Stops autospin
			 */
			this.stop = function() {
				if (this.controller!=0) {
					clearInterval(this.controller);
					this.controller = 0;
				}
			}
			
			/*
			 * Starts autospin
			 */
			this.go = function() {
				if (this.settings.autospin != 0) {
					if (this.controller==0) {
						this.controller = setInterval(function() {
							var next=context.current+1;
							if (next > context.elements.length-1) next=0;
							context.rotateto(next);
						}, this.settings.autospin*1000);
					}
				}
			}
			
			/*
			 * Initialisation
			 */
			
			if (options) {
				$.extend(this.settings, options);
			}
			
			context=this;
			
			this.createimages(images);
			this.placeimages();
			this.go();
			
			$(this).mouseleave(function() {
				context.go();
			});
		}
		
	})(jQuery);

	/*
	 * A special easing
	 */
	jQuery.extend(jQuery.easing, {
		w2dplugincarouseleasing: function(x, t, b, c, d){
			if ((t /= d / 2) < 1) 
				return c / 2 * t * t + b;
			return -c / 2 * ((--t) * (t - 2) - 1) + b;
		}
	});
}
