/**
 * Interface Elements for jQuery
 * 3D Carousel
 * 
 * http://interface.eyecon.ro
 * 
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt) 
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 */
/**
 * Created a 3D Carousel from a list of images, with reflections and animated by mouse position
 * 
 * @example window.onload = 
 *			function()
 *			{
 *				$('#carousel').Carousel(
 *					{
 *						itemWidth: 110,
 *						itemHeight: 62,
 *						itemMinWidth: 50,
 *						items: 'a',
 *						reflections: .5,
 *						rotationSpeed: 1.8
 *					}
 *				);
 *			}
 * HTML
 *			<div id="carousel">
 *				<a href="" title=""><img src="" width="100%" /></a>
 *				<a href="" title=""><img src="" width="100%" /></a>
 *				<a href="" title=""><img src="" width="100%" /></a>
 *				<a href="" title=""><img src="" width="100%" /></a>
 *				<a href="" title=""><img src="" width="100%" /></a>
 *			</div>
 * CSS
 *			#carousel
 *			{
 *				width: 700px;
 *				height: 150px;
 *				background-color: #111;
 *				position: absolute;
 *				top: 200px;
 *				left: 100px;
 *			}
 *			#carousel a
 *			{
 *				position: absolute;
 *				width: 110px;
 *			}
 *
 * @desc Creates a 3D carousel from all images inside div tag with id 'carousel'
 *
 *
 * @name 3D Carousel
 * @description Created a 3D Carousel from a list of images, with reflections and animated by mouse position
 * @param Hash hash A hash of parameters
 * @option String items items selection
 * @option Integer itemWidth the max width for each item
 * @option Integer itemHeight the max height for each item
 * @option Integer itemMinWidth the minimum width for each item, the height is automaticaly calculated to keep proportions
 * @option Float rotationSpeed the speed for rotation animation
 * @option Float reflectionSize the reflection size a fraction from items' height
 *
 * @type jQuery
 * @cat Plugins/Interface
 * @author Stefan Petre
 */
jQuery.iCarousel = {
	
	build : function(options)
	{
		var publicObj;
		this.each(function() {
			var el = this;
			var increment = 2*Math.PI/360;
			var maxRotation = 2*Math.PI;
			if(jQuery(el).css('position') != 'relative' && jQuery(el).css('position') != 'absolute') {
				jQuery(el).css('position', 'relative');
			}
			el.carouselCfg = {
				items : jQuery(options.items, this),
				itemWidth : options.itemWidth,
				itemHeight : options.itemHeight,
				itemMinWidth : options.itemMinWidth,
				maxRotation : maxRotation,
				size : jQuery.iUtil.getSize(this),
				position : jQuery.iUtil.getPosition(this),
				start : Math.PI/2,
				rotationSpeed : options.rotationSpeed,
				reflectionSize : options.reflections,
				reflections : [],
				protectRotation : false,
				increment: 2*Math.PI/360,
				moveInterval : 20
			};
			el.carouselCfg.radiusX = (el.carouselCfg.size.w - el.carouselCfg.itemWidth)/2;
			el.carouselCfg.radiusY =  (el.carouselCfg.size.h - el.carouselCfg.itemHeight - el.carouselCfg.itemHeight * el.carouselCfg.reflectionSize)/2;
			el.carouselCfg.step =  2*Math.PI/el.carouselCfg.items.size();
			el.carouselCfg.paddingX = el.carouselCfg.size.w/2;
			el.carouselCfg.paddingY = el.carouselCfg.size.h/2 - el.carouselCfg.itemHeight * el.carouselCfg.reflectionSize;
			var reflexions = document.createElement('div');
			jQuery(reflexions)
				.css(
					{
						position: 'absolute',
						zIndex: 1,
						top: 0,
						left: 20
					}
				);
			jQuery(el).append(reflexions);
			el.carouselCfg.items
				.each(
					function(nr)
					{
						image = jQuery('img', this).get(0);
						height = parseInt(el.carouselCfg.itemHeight*el.carouselCfg.reflectionSize);
						if (jQuery.browser.msie) {
							canvas = document.createElement('img');
							jQuery(canvas).css('position', 'absolute');
							canvas.src = image.src;				
							canvas.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity=60, style=1, finishOpacity=0, startx=0, starty=0, finishx=0)';
				
						} else {
							canvas = document.createElement('canvas');
							if (canvas.getContext) {
								context = canvas.getContext("2d");
								canvas.style.position = 'absolute';
								canvas.style.height = height +'px';
								canvas.style.width = el.carouselCfg.itemWidth+'px';
								canvas.height = height;
								canvas.width = el.carouselCfg.itemWidth;
								context.save();
					
								context.translate(0,height);
								context.scale(1,-1);
								
								context.drawImage(
									image, 
									0, 
									0, 
									el.carouselCfg.itemWidth, 
									height
								);
				
								context.restore();
								
								context.globalCompositeOperation = "destination-out";
								var gradient = context.createLinearGradient(
									0, 
									0, 
									0, 
									height
								);
								
								gradient.addColorStop(1, "rgba(255, 255, 255, 1)");
								gradient.addColorStop(0, "rgba(255, 255, 255, 0.6)");
					
								context.fillStyle = gradient;
								if (navigator.appVersion.indexOf('WebKit') != -1) {
									context.fill();
								} else {
									context.fillRect(
										0, 
										0, 
										el.carouselCfg.itemWidth, 
										height
									);
								}
							}
						}
						
						el.carouselCfg.reflections[nr] = canvas;
						jQuery(reflexions).append(canvas);
					}
				)
				.bind(
					'mouseover',
					function(e)
					{
						el.carouselCfg.protectRotation = true;
						el.carouselCfg.speed = el.carouselCfg.increment*0.1 * el.carouselCfg.speed / Math.abs(el.carouselCfg.speed);
						return false;
					}
				)
				.bind(
					'mouseout',
					function(e)
					{
						el.carouselCfg.protectRotation = false;
						return false;
					}
				);
			jQuery.iCarousel.positionItems(el);
			el.carouselCfg.speed = el.carouselCfg.increment*0.2;
			el.carouselCfg.rotationTimer = setMyInterval();
			
			function setMyInterval() {
				return window.setInterval(
					function() {
						el.carouselCfg.start += el.carouselCfg.speed;
						if (el.carouselCfg.start > maxRotation)
							el.carouselCfg.start = 0;
						jQuery.iCarousel.positionItems(el);
					},
					el.carouselCfg.moveInterval
				);
			};
			
			function stop () {
				window.clearInterval(el.carouselCfg.rotationTimer);
			};
			function start () {
				el.carouselCfg.rotationTimer = setMyInterval();
			};
			
			var publicFn = {
				stop : stop,
				start : start
			};
			
			jQuery(el)
				.bind(
					'mouseout',
					function()
					{
						el.carouselCfg.speed = el.carouselCfg.increment*0.2 * el.carouselCfg.speed / Math.abs(el.carouselCfg.speed);
					}
				)
				.bind(
					'mousemove',
					function(e)
					{
						if (el.carouselCfg.protectRotation == false) {
							pointer = jQuery.iUtil.getPointer(e);
							mousex =  el.carouselCfg.size.w - pointer.x + el.carouselCfg.position.x;
							el.carouselCfg.speed = el.carouselCfg.rotationSpeed * el.carouselCfg.increment * (el.carouselCfg.size.w/2 - mousex) / (el.carouselCfg.size.w/2);
						}
					}
				);
			publicObj = publicFn;
			return publicFn;
		});
		return publicObj;
	},

	positionItems : function(el)
	{
		el.carouselCfg.items.each(
			function (nr)
			{
				angle = el.carouselCfg.start+nr*el.carouselCfg.step;
				x = el.carouselCfg.radiusX*Math.cos(angle);
				y = el.carouselCfg.radiusY*Math.sin(angle) ;
				itemZIndex = parseInt(100*(el.carouselCfg.radiusY+y)/(2*el.carouselCfg.radiusY));
				parte = (el.carouselCfg.radiusY+y)/(2*el.carouselCfg.radiusY);
				
				width = parseInt((el.carouselCfg.itemWidth - el.carouselCfg.itemMinWidth) * parte + el.carouselCfg.itemMinWidth);
				height = parseInt(width * el.carouselCfg.itemHeight / el.carouselCfg.itemWidth);
				this.style.top = el.carouselCfg.paddingY + y - height/2 + "px";
	     		this.style.left = el.carouselCfg.paddingX + x - width/2 + "px";
	     		this.style.width = width + "px";
	     		this.style.height = height + "px";
	     		this.style.zIndex = itemZIndex;
				el.carouselCfg.reflections[nr].style.top = parseInt(el.carouselCfg.paddingY + y + height - 1 - height/2) + "px";
				el.carouselCfg.reflections[nr].style.left = parseInt(el.carouselCfg.paddingX + x - width/2) + "px";
				el.carouselCfg.reflections[nr].style.width = width + "px";
				el.carouselCfg.reflections[nr].style.height = parseInt(height * el.carouselCfg.reflectionSize) + "px";
			}
		);
	}
};
jQuery.fn.Carousel = jQuery.iCarousel.build;
