/*
 * Create a 3D carousel similar to the popular Flash carousel
 *
 * @name		carousel3d
 * @author		Kevin Crossman
 * @contact		kevincrossman@gmail.com
 * @version		0.4
 * @date			Sep 10 2008
 * @type    	 	jQuery
 * @example  
 *
 *
 *	 	* Place images inside $('#carousel')
 *
 * 				<div id='carousel'>
 *						<img src='images/image1.png' alt='image1' /> 
 *						<img src='images/image2.png' alt='image2' /> 
 *						<img src='images/image3.png' alt='image3' /> 
 *						<img src='images/image4.png' alt='image4' /> 
 *
 *	 	* add class 'link' and set id to a web address to make the image a page link
 *						<img class="link" id="http://plugins.jquery.com/" src='images/image5.png' alt='image5'  /> 
 *						<img class="link" id="http://jquery.com/" src='images/image6.png' alt='image6' /> 
 *
 *				</div>
 *
 *
 */
(function($) {

	var opt;

    $.fn.carousel3d = function(options) {

        return this.each(function() {

           	opt = $.extend({},$.fn.carousel3d.defaults, options);

            $this = $(this); // $this = #carousel
            $imgs = $('img', $this).hide(); // $imgs = images in #carousel
            var items = $this.children().size(); // items = the number of visible images circling the carousel
            var numSlots = items * opt.padding; // in order for the movement to flow smoothly, there are additional 'slots' in the carousel which the images will pace through

            if (opt.padding == 0) opt.padding = 1;

            $o = {};
            var w_h = new Array();
            
            // assign inital values to images; 
            $imgs.each(function(i) {

                w_h = resize($(this).width(), 128, $(this).height(), 108).split('|');
                
                this._img = $(this);
                this._h = w_h[1];
                this._w = w_h[0];
                this.slot = i * opt.padding;
                this.angle = (i * opt.padding) * ((Math.PI * 2) / numSlots);
                
                this.onAnimate =  { 
                		top: opt.centerY - $(this).height()/3 + 'px',
                        left: opt.centerX - $(this).width()/3 + 'px',
                        width: $(this).width() + 'px',
                        height: $(this).height() + 'px'  };
                 
                $o[i] = this;
                 $(this).addClass('pix' + i).css({position: 'absolute'});
				 
				 
				if(opt.control=='timer'){
					$(this).mouseover(function(){opt.speed = 0;});
					$(this).mouseout(function(){opt.speed = opt.delay;});
				}
            });

             // setup tooltip for images
			$imgs.one('click', clickOn);
						
            controls();
            
			// javascript Motion Tween by PHILIPPE MAEGERMAN; very similar to tweening in Flash.
			// check out the full details at his site: http://jstween.blogspot.com/
            t1 = new Tween(new Object(), 'xyz', Tween.regularEaseInOut, 0, 10000, 10000);
            
            t1.onMotionChanged = function(event) {
               
               for (var j = 0; j < items; j++) {
                    
                    $o[j].slot = ($o[j].slot == numSlots - 1) ? 0 : $o[j].slot + 1;
                    
                    var _t = Math.sin($o[j].angle) * opt.radiusY + opt.centerY;
                    var _l = Math.cos($o[j].angle) * opt.radiusX + opt.centerX;
                    var _s = ((_t - opt.perspective) / (opt.centerY + opt.radiusY - opt.perspective));
                    
                    $o[j].angle += opt.speed;
                    
                    $o[j]._img.css({ top: _t, left: _l, width: $o[j]._w * _s, height: $o[j]._h * _s, zIndex: Math.round(_t)+100 });
                }
            };
            t1.start();
            $imgs.fadeIn(1500);

        });

    };

	function resize(w, max_w, h, max_h) {
		// return w|h
		if (w>max_w || h>max_h) {
			var x_ratio = max_w / w;
			var y_ratio = max_h / h;
			if ((x_ratio * h) < max_h) return max_w + '|' + Math.ceil(x_ratio * h);
			else return Math.ceil(y_ratio * w) + '|' + max_h;
		}
		else return w + '|' + h;
	}
	
	function controls() {	// add or remove mouse/button functions
        
        if (opt.control=='buttons') {
        	opt.speed=0;
     		$('body')
            	.append($('<div id="buttonwrapper"></div>').css({ left: opt.centerX+'px', top: opt.centerY+200*1+'px'})
           		.append(
       				$('<div id="left"></div>')
        				.mouseover(function() { opt.speed = ($.browser.msie) ? .05 : .15 })
            			.mouseout(function() { opt.speed = 0 }), 
           			$('<div id="right"></div>')
          				.mouseover(function() { opt.speed = ($.browser.msie) ? -.05 : -.15 })
      					.mouseout(function() { opt.speed = 0 })
   				));
		}
		else if(opt.control=='timer'){
			opt.speed = opt.delay;
		}
		else {
			$().mousemove(function(e) {
                	opt.speed = ($.browser.msie) ? (e.pageX - opt.centerX) / 5000 : (e.pageX - opt.centerX) / 2500;
      	 	});
		}
    }
	
	// set up actions to reset carousel when image is clicked again
	function clickOff(obj, obj2, lft, tp) {	// set up actions to reset carousel when image is clicked again

		obj.click(function() {
         	
         	// show the carousel images and remove text
            $imgs.fadeIn(1500);

             // animate back to carousel position, changing location and size
             $(this).animate({ left: lft, top: tp, width: obj2.width() + 'px', height: obj2.height() + 'px' }, 300,
				function() {	
					$(this).remove();					//remove the cloned image, 
            		$imgs.one('click', clickOn);	//rebind the img click events and start carousel,
            		t1.start();								//restart carousel 
          		});
          	});
	};

	function clickOn() {	// actions when image in carousel is clicked

		$ths = this;
		
		if ($(this).hasClass('link')) {
			window.open(this.id);
		} else {
			t1.stop(); // stop the Tween motion
			// clone the image clicked and leave the original in place (this seemed easier than pulling the orig out of place)
			// animate the clone to the side of the screen
			$cloned = $(this)
								.clone()
								.prependTo($this)
								.css('border', '4px solid #ddd')
								.animate( { top: opt.centerY - $($ths).height()/3 + 'px',
					                        left: opt.centerX - $($ths).width()/3 + 'px',
					                        width: $ths.onAnimate.width,
					                        height: $ths.onAnimate.height
										  } ,500);
								//.animate($ths.onAnimate,500);
				
			$imgs.fadeOut(500); // hide the carousel
				
			clickOff($cloned, $(this), $(this).position().left + 'px', $(this).position().top + 'px');
        }
    };
	
	
	$.fn.setCenter = function(x, y){
		opt.centerX = x;
		opt.centerY = y;
	};
	
	$.fn.setRadus = function(r_x, r_y){
		opt.radiusX = r_x;
		opt.radiusY = r_y;
	};
	

    // plugin defaults
    $.fn.carousel3d.defaults = {
        control: 'mouse',	 	
        //  1 = mouse controls movement, 0 = buttons control movement
        speed: ($.browser.msie) ? 0.05 : 0.3,
        // x radius of the carousel
        radiusX: 200,
        // x radius of the carousel
        radiusY: 50,
        // y radius of the carousel
        centerX: 550,
        // x position on the screen
        centerY: 250,
        // y position on the screen
        perspective: 150,
        // adjusts the perspective of the icon as it travels around the carousel
        padding: 24 // the number of padded items in between each icon.  
        // the more padding, the more precise the incremental movement,
        // however this also create a lot more calculations
        // to keep icons evenly spaced, the num of icons should be a multiple of the padding
    };
		
})(jQuery);
