/*
 * Paul Bakaus' Carousel @VERSION
 *
 * Copyright (c) 2008 Paul Bakaus
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 */
(function($){

$.widget("ui.carousel", {
	
	_init: function() {
		

		var self = this;
		this.items = $(this.options.items, this.element);
		
//		this.items = $(this.options.items, this.element).css({ position: "absolute", top: 0, left: 0, zIndex: 1 });
		$.extend(this, {
			props: this.options.orientation == 'vertical' ? ['height', 'Height', 'top', 'Top'] : ['width', 'Width', 'left', 'Left'],
			start: Math.PI/2,
			speed: this.options.speed, //We need a default spead so the initialization works
			direction: 'left', //This is a live property, toggled during interaction
			step: 2*Math.PI/this.items.length,
			paddingX: (this.element.outerWidth() - this.options.adjustmentX) / 2,
			paddingY: (this.element.outerHeight() - this.options.adjustmentY) / 2,
			itemHeight: this.options.height || this.items.height(),
			itemWidth: this.options.width || this.items.width()
		});

		//Add pause/resume functionality when you hover a item
		this.items
			.css({ position: "absolute", top: 0, left: 0, zIndex: 1 });
//			.hover(function(e) {
//				if(self.options.pausable) self.pause();
//			},function(e) {
//				self.resume();
//			});
			

		//Little trick to jump to the first item
		this.rotate("left");
		this.rotate("right");
		
		//Auto animation for the carousel
		if(this.options.animate)
			self._startAnimation();

		this.offset = this.element.offset();
		this.targetItem = 0;
		
//		$(this.options.handle || this.element)
//			.bind('mouseenter', function() {
//				self.offset = self.element.offset();
//			})
//			.bind('mouseleave.carousel', function() {
//				self.options.animate ? self._startAnimation() : self.interval && clearInterval(self.interval);
//			})
//			.bind("mousemove.carousel", function(e) {
//	
//				if(self.paused || !self.options.animateByMouse) return;
//				var mod = ((e[self.options.orientation == 'vertical' ? 'pageY' : 'pageX']-self.offset[self.props[2]]) - this['offset'+self.props[1]]/2);
//				
//				self.speed = Math.abs(mod)/5000;
//				self.direction = mod < 0 ? "right" : "left";
//	
//		});
	},
	
	_setData: function(key, value) {
		$.widget.prototype._setData.apply(this, arguments);
		if(key == 'height') this.itemHeight = value;
		if(key == 'width') this.itemWidth = value;
	},

	destroy: function() {

		clearInterval(this.interval);
		this.element.unbind('.carousel');
		
		var self = this;
		window.setTimeout(function() {
			self.items.css({ left: '', top: '', position: '', height: '', width: '' }).unbind('.carousel');
			self.element.removeData('carousel');
		}, 0);

	},
	
	_startAnimation: function() {

		var self = this;
		this.speed = self.options.animate;

		this.interval && clearInterval(this.interval);
		this.interval = window.setInterval(function() { self.rotate(); }, 13);

	},
	
	resume: function() {
		this.paused = false;
		this.options.animate && this._startAnimation();
		this._trigger('resume');
	},
	
	pause: function() {

		var self = this;
		this.paused = true;

		this.options.pauseSpeed ? (this.speed = self.options.pauseSpeed) : (this.interval && clearInterval(this.interval));
		this._trigger('pause');

	},
	
	select: function(item) {
		
		this.currentItem = !isNaN(parseInt(item,10)) ? parseInt(item,10) : this.items.index(item);
		
		this.start = Math.PI/2;
		this.rotate('left', this.step * item);
		
		this._trigger('select', null, {
			value: item,
			item: this.items[item] 
		});
		
	},
	
	moveTo: function(index)
	{
		this.targetItem = index;
		
		if (0 > this.targetItem)
		{
			this.targetItem = this.items.length + this.targetItem;
		}
		else if (this.targetItem > (this.items.length - 1))
		{
			this.targetItem = 0;
		}
		
		this.options.animate = this.options.speed;
		this.resume();
	},
	
	moveNext: function()
	{
		this.direction = "right";
		this.moveTo(this.targetItem + 1);
	},
	
	movePrevious: function()
	{
		this.direction = "left";
		this.moveTo(this.targetItem - 1);
	},
	
//	pause: function() {
//
//		var self = this;
//		this.paused = true;
//		if(this.interval) clearInterval(this.interval);
//
//		if(this.options.pauseSpeed) {
//			this.interval = window.setInterval(function() {
//				self.rotate('left',0.001);
//			}, 13);
//		}
//	},
	
	rotate: function(direction, speed) {

		var o = this.options, self = this;

		direction = direction || this.direction;
		this.speed = speed !== undefined ? speed : this.speed;
		
		this.start = this.start + (direction == "right" ? (-1 * this.speed) : this.speed);
		var rotate_radius = Math.min(400, Math.pow(self.step, -.5) * o.radius);
		
		self.items.each(function(i) {

			//var x = Math.min(0, self.options.radius * Math.cos(angle)); w00t! this makes a half carousel
			var angle = self.start + i * self.step,
				x = rotate_radius * Math.cos(angle),
				y = self.options.tilt * Math.sin(angle),
				modifier = (1 - (self.options.tilt+y) / (2 * self.options.tilt)) * Math.max(1, parseInt(self.items.length / 3)),
				width = Math.max(self.itemWidth - (o.distance * self.itemWidth), self.itemWidth * (1 - modifier)),
				height = parseInt(width * self.itemHeight / self.itemWidth,10);
			
			var difference = (self.itemWidth - width);
			
			var min_difference = Math.min(1, self.step * 2);
			
			$.extend(this.style, {
				top: self.paddingY + (self.options.orientation == 'vertical' ? x : y) - height/2 + "px",
				left: self.paddingX + (self.options.orientation == 'vertical' ? y : x) - width/2 + "px",
				width: width + "px",
				height: height + "px",
				zIndex: (min_difference > difference) ? 1000 : parseInt(100 * (self.options.tilt+y) / (2 * self.options.tilt),10),
				fontSize: (min_difference > difference) ? .8 + "em" : Math.max(0, .8 - modifier) + "em",
				opacity: (min_difference > difference) ? 1 : Math.max(0, 1 - modifier),
				display: (20 > width) ? 'none' : 'block'
			});
			
			if (min_difference > difference)
			{
				self.selectedItem = i;

				if (self.selectedItem == self.targetItem && false == self.paused)
				{ 
					self.pause();
					if (false != self.options.onComplete)
					{
						self.options.onComplete.call(this, self);
					}
				}
			}
		});
	}
	
});

$.extend($.ui.carousel, {
	defaults: {
		distance: 0.99,
		handle: false,
		radius: 200,
		tilt: -0.1,
		items: '> *',
		orientation: 'auto',
		direction: 'left',
		radiusX: 200,
		radiusY: -0.1,
		animate: 0.005,
		animateByMouse: true,
		pausable: true,
		speed: 0.03,
		pauseSpeed: false, //If you don't want to actually stop the carousel when hovering items, set it to something small, i.e. 0.001
		smallerItems: false, //This creates a somewhat fake mode. Looks better on some wide carousels, the items are smaller
		onComplete: false,
		adjustmentX: 0,
		adjustmentY: 0
	}
});
	
})(jQuery);