/*
 * 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 icon 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 an address to the name attribute to make the image a link
 *						<img src='images/image5.png' alt='image5' name="http://plugins.jquery.com/" /> 
 *						<img src='images/image6.png' alt='image6' name="http://jquery.com/" /> 
 *
 *				</div>
 *
 *	 	* Place corresponding spans inside $('#carouselText')
 * 		* spans  contains content that will be displayed when the icon is clicked *
 *				<div id="carouselText">
 *						<span>customize this space for icon 1</span>
 *						<span>customize this space for icon 2</span>
 *						<span>customize this space for icon 3</span>
 *						<span>customize this space for icon 4</span>
 *				</div>
 *
 *	 	* End with a div to display the content from $('#carouselText span')
 *
 * 				<div class="text"></div>
 *
 */
 (function($) {

    var opt;

    $.fn.carousel3d = function(options) {

        return this.each(function() {

            setCurrentOptions(options);
            $this = $(this);
            // $this = #carousel
            $imgs = $('img', $this).hide();
            // $imgs = images in #carousel
            $texts = $('span', $('#carouselText')).hide();
            // $texts = spans that store the text info displayed when an image is clicked
            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 = {};

            // assign inital values to images; 
            $imgs.each(function(i) {
                w_h = resize($(this).width(), 128, $(this).height(), 108).split('|');

                this._w = w_h[0];
                this._h = w_h[1];
                this._orig_w = $(this).width();
                this._orig_h = $(this).height();
                this._img = $(this);
                this.slot = i * opt.padding;
                this.angle = (i * opt.padding) * ((Math.PI * 2) / numSlots);

                this.onAnimate = {
                    top: opt.centerY - this._orig_h / 3 + 'px',
                    left: opt.centerX - this._orig_w / 2 + 'px',
                    width: this._orig_w + 'px',
                    height: this._orig_h + 'px',
					filter:"Alpha(opacity=100)",
					opacity:1
                };
				// for onTextBoxAnimate, changed left:0 to left:opt.centerX + opt.radiusX + 'px' for Vero site by Chuong Vu on 30/12/08
				// for onTextBoxAnimate, changed top: opt.centerY - this._orig_h / 3 + 'px' to top: opt.centerY - opt.radiusY * 1.5 + 'px' for Vero site by Chuong Vu on 30/12/08				
                this.onTextBoxAnimate = {
//                    left: opt.centerX + opt.radiusX + 'px',
//                    top: opt.centerY - opt.radiusY * 1.5 + 'px',
                    left: (opt.centerX - this._orig_w / 2) + 'px',
                    top: (opt.centerY - 70) + 'px',
					width: this._orig_w + 'px',
                    height: this._orig_h + 'px',
					filter:"Alpha(opacity=25)",
					opacity:0.3
                };
                this.onTextBoxCss = {
//                    top: opt.centerY - opt.radiusY * 1.5 + 'px',
                    top: opt.centerY - 70 + 'px',
                    left: opt.centerX - this._orig_w / 2 + 'px'
                };
                this.textBoxHtml = $texts.eq(i).html();

                $o[i] = this;
                if (opt.border) $(this).addClass('pix' + i).css({position: 'absolute',border: '2px solid #ddd'});
                else $(this).addClass('pix' + i).css({position: 'absolute'});
                
                if ($(this).hasClass('tt')) $(this).tooltip({ track: true, delay: 500, showURL: false, showBody: "|", opacity: 0.95, top: -150, left: -100 });
                
            });

             // setup tooltip for images
			$imgs.one('click', clickOn);
            
			// 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) {
				var maxT = 0;
				var frontRunner = "";
                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 -50;
                    var _s = ((_t - opt.perspective) / (opt.centerY + opt.radiusY - opt.perspective));
                    $o[j].angle += Math.max((0-opt.maxspeed),Math.min(opt.maxspeed,((opt.control == 'buttons') ? opt.buttonspeed: opt.mousespeed)));
                    $o[j]._img.css({
                        top: _t,
                        left: _l,
                        width: Math.round($o[j]._w * _s) + 'px',
                        height: Math.round($o[j]._h * _s) + 'px',
						zIndex: Math.round(_t)+100,
						filter: "Alpha(opacity="+_s*_s*100+")",
						opacity: _s*_s
                    });
					if(_t > maxT) {
						maxT = _t;
						frontRunner = $o[j]._img.attr("alt");
					}
                }
				if($("#featureProduct").text()!=frontRunner){
					$("#featureProduct").text(frontRunner);
				}
            };

            t1.start();
            $imgs.fadeIn(1500);
        });
    };
    
	$(window).resize(function() {
		opt.centerX = ($('#productCarousel').offset().left+$('#productCarousel').width()/2);
		resetAnimations();
	});
	
	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 resetAnimations() {
		$imgs.each(function(i) {
		   	this.onAnimate['left'] = opt.centerX - this._orig_w/2 + 'px';
			// for onTextBoxAnimate, changed opt.centerX - opt.radiusX - this._w + 'px' to opt.centerX + opt.radiusX + 'px' for Vero site by Chuong Vu on 30/12/08
       		this.onTextBoxAnimate['left'] = opt.centerX + opt.radiusX + 'px';
           	this.onTextBoxCss['left'] = opt.centerX - opt.radiusX + 'px';
		});
		 $('UL#options LI SPAN').each(function(i) { $(this).html(opt[this.className]);  });
	}
	
	function clickOff(obj, obj2, lft, tp) {	// set up actions to reset carousel when image is clicked again
		
		obj.add('#carouselTextDisplay a.closeImg').click(function() {
			$imgs.fadeIn(500);							// show the carousel images & buttons
			$('#buttonwrapper:hidden, #featureProduct').fadeIn(500);
			$('a.closeImg').hide();
			$('#carouselTextDisplay').fadeOut(700);						// remove text
			// animate back to carousel position, changing location and size
			$(obj).animate({ left: lft, top: tp, width: obj2.width() + 'px', height: obj2.height() + 'px' }, 500,
				function() {	
					$(obj).remove();					//remove the cloned image, 
            		$imgs.one('click', clickOn);	//rebind the img click events and start carousel,
            		t1.start();								//restart carousel 
          		});
			return false;
       	 });
	};
	
	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
			$('#buttonwrapper:visible, #featureProduct').fadeOut(500);
			
			if (!opt.textBox) {
				$cloned = $(this)
									.clone()
									.prependTo($this)
									.css('border', '4px solid #ddd')
									.animate($ths.onAnimate,500);
			} else {
				$cloned = $(this)
									.clone()
									.prependTo($this)
									.animate($ths.onTextBoxAnimate, 500);
				$('#carouselTextDisplay')
					.css( $ths.onTextBoxCss )
					.css({
						 width: this._orig_w + 'px',
	                    height: this._orig_h + 'px'})
					.html( $("#carouselTextHeader").html() + $ths.textBoxHtml )
					.fadeIn(700);
				}
				$imgs.fadeOut(700); // hide the carousel
				$('a.closeImg').show();				
				clickOff($cloned, $(this), $(this).position().left + 'px', $(this).position().top + 'px');
          	}
	};
	
	
    function controls() {	// add or remove mouse/button functions
        if (opt.control=='buttons') {
            $().unbind('mousemove');
            if (!opt.sp)
                opt.sp = opt.buttonspeed;
            opt.buttonspeed = 0;
            $('.maincol')
            	.append(
            		$('<div id="buttonwrapper"></div>')
          				.css({left: opt.centerX+'px', top: opt.centerY+opt.radiusY+140*1+'px'})
            			.append(
            				$('<div id="left"></div>')
            					.mouseover(function() { opt.buttonspeed = opt.sp })
            					.mouseout(function() { opt.buttonspeed = 0 }), 
           					$('<div id="right"></div>')
          						.mouseover(function() { opt.buttonspeed = -opt.sp })
            					.mouseout(function() { opt.buttonspeed = 0 })
            				));
		}
		else {
			$('#buttonwrapper').remove();
			$("#productCarousel, #carousel").mousemove(function(e) {
				var xdev = e.pageX - opt.centerX;
				var ydev = e.pageY - opt.centerY;
                opt.mousespeed = (e.pageX - opt.centerX) / opt.speedfactor;
			}).bind("mouseenter",function(e) {
				var xdev = e.pageX - opt.centerX;
				var ydev = e.pageY - opt.centerY;
                opt.mousespeed = (e.pageX - opt.centerX) / opt.speedfactor;
			}).bind("mouseleave",function(){
				opt.mousespeed = opt.defaultspeed * opt.mousespeed / Math.abs(opt.mousespeed);
			});
		}
    }
    function setCurrentOptions(options) {
       	opt = $.extend({},	$.fn.carousel3d.defaults, options);
        $('select').each(function(i) {  $(this).val(opt[$(this).attr('name')]);  });
        $('UL#options LI SPAN').each(function(i) { $(this).html(opt[this.className]);  });
        $('#buttonwrapper').remove();
        controls();
    }

    function setSettings(settings) {
        $.extend(opt, settings);
    }

    $.carouselSettings = function(settings) {
        setSettings(settings);
        if (settings['control'])
            controls();
    }

    // plugin defaults
    $.fn.carousel3d.defaults = {
        control: 'mouse',	 	//  1 = mouse controls movement, 0 = buttons control movement
        border: 0,					//  border for carousel images
        mousespeed: ($.browser.msie) ? 0.01 : 0.01,				//  circling speed
        buttonspeed: ($.browser.msie) ? 0.01 : 0.2,				//  circling speed
		defaultspeed: ($.browser.msie) ? 0.01 : 0.01,				//  circling speed
		maxspeed: ($.browser.msie) ? 0.02 : 0.04,  //max circling speed
		speedfactor: ($.browser.msie) ? 5000 : 5000, // speed is distance from center divided by this factor.
        textBox: 1,			 	//  1 = display text area for each icon, 0 = no display
        radiusX: 300,			// x radius of the carousel
        radiusY: 90,			// y radius of the carousel
        centerX: 550,			// x position on the screen
        centerY: 350,			// y position on the screen
        perspective: 200,		// 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);