$.fn.carousel3D = function(options) {
    
    var parentContainer = this;
    var settings = $.extend({
        speed: 350,
        perspectiveZoom : 80,
        sideOffset: 70,
        topOffset:0,
        emClass: "tdc-element",
        secondaryOpacity:0.8,
		fadeAwayOpacity:0,
		fullOpacity:100,
        states : [],
		ready: false
    }, options);
	
	var theClicked;
	
    var emClass = settings.emClass;
    var elements = this.find("."+emClass);
    var mutex = false;
    this.find("."+emClass).css("position","absolute");
    this.find("."+emClass).css("overflow","hidden");
    $(this).css("position","relative");
    var lastEm = elements.length - 1;

    var initW = $(elements[1]).width();
    var initH = $(elements[1]).height();
    var initWS = initW * settings.perspectiveZoom/100;
    var initHS = initH * settings.perspectiveZoom/100;
	var initHSB = initHS * settings.perspectiveZoom/100;
	var initWSB = initWS * settings.perspectiveZoom/100;
	var initHSBC = initHSB * settings.perspectiveZoom/100;
	var initWSBC = initWSB * settings.perspectiveZoom/100;


    settings.states = [
		{height: initHSBC, width: initWSBC, top:(initHS-initHSB)/2+settings.topOffset*1.9, left: settings.sideOffset + initW/2 - initWSBC/2, opacity: settings.secondaryOpacity/4},
		{height:initHSB, width:initWSB, top:(initHS-initHSB)/2+settings.topOffset*1.8, left:settings.sideOffset - initW/2 + 15, opacity:settings.secondaryOpacity/2},
        {height:initHS, width:initWS, top:(initH-initHS)/2+settings.topOffset, left:-30, opacity:settings.secondaryOpacity},
        {height:initH, width:initW, top:-40, left:settings.sideOffset, opacity:settings.fullOpacity},
        {height:initHS,width:initWS, top:(initH-initHS)/2+settings.topOffset, left:2*settings.sideOffset+initW - initWS + 30, opacity:settings.secondaryOpacity},
		{height:initHSB,width:initWSB, top:(initHS-initHSB)/2+settings.topOffset*1.8, left:2*settings.sideOffset + initWSB - initWS/2 - 15, opacity:settings.secondaryOpacity/2}
    ];

    /*for(var j=6;j<=lastEm;j++){
        settings.states[j] = {height:0, width:0, top:(initH)/2, left:settings.sideOffset+initW/2, opacity:settings.fadeAwayOpacity};
    }*/

    function transit(direction) {
        mutex = true;
		if(direction){
			var leftVal;
			for (var j = 0; j<=lastEm;j++){
				leftVal = parseInt($(elements[j]).css("left"), 10);
				var left = (leftVal > 100);
				$(elements[j]).css({zIndex: left ? 10-j : j});
			}
		}else{
			var leftVal;
			for (var j = 0; j<=lastEm;j++){
				leftVal = parseInt($(elements[j]).css("left"), 10);
				var left = (leftVal < 100);
				$(elements[j]).css({zIndex: left ? j : 10-j});
			}
		}
		
		//theClicked;
        $(elements).each(function(i){
            $(elements[i]).animate(settings.states[direction ? (i == 0 ? lastEm : i - 1) : (i == lastEm ? 0 : i + 1)], settings.speed, 'swing', function(){
                if (i==lastEm){
                    var prevState = elements;
                    elements = [];
                    elements[0] = prevState[direction ? 1 : lastEm];
                    elements[lastEm] = prevState[direction ? 0 : lastEm-1];
                    for(var j=1;j<lastEm;j++)
                        elements[j] = prevState[direction ? j+1 : j-1];
    
                    $(elements).each(function(){
                       /*$(elements[1]).css({zIndex: 200});
                       $(elements[2]).css({zIndex: 100});
                       $(elements[0]).css({zIndex: 100});*/
                       for(var j = 0; j<=lastEm;j++)
                           $(elements[j]).css({zIndex: direction ? 10-j : j});
                    });
					
					if(theClicked.css("left") != "165px"){
						transit(direction);
					}else{
						showCurrent(theClicked.attr("id")); //show the current div somehow
						mutex = false;
					}
                }
            });
        });
    
       /* setTimeout(function(){
            /*$(elements[0]).css({zIndex: direction ? 100 : 200});
            $(elements[1]).css({zIndex: 100});
            $(elements[2]).css({zIndex: direction ? 200 : 100});
            for (var j = 0; j<=lastEm;j++)
                $(elements[j]).css({zIndex: direction ? 10-j : j});
        }, settings.speed / 2);*/

    }

    $(elements).each(function(){
        $(this).click(function(e){
            if(mutex || !settings.ready) {
                return;
            }
            if(this === elements[0] || this === elements[1] || this === elements[2]) {
				theClicked = jQuery(e.target);
				if(theClicked.css("left") != "165px"){
					transit(false);
				}
            }
            else {
				theClicked = jQuery(e.target);
                if(theClicked.css("left") != "165px"){
					transit(true);
				}
            }
        });
    });
	
	jQuery('.tdc-element').hover(function(){
			if(!mutex){
				currentOp = jQuery(this).css("opacity");
				jQuery(this).animate({"opacity": currentOp*2.4}, 20);
			}
		},
		function(){
			if(!mutex){
				jQuery(this).animate({"opacity": currentOp}, 20);
			}
		}
	);
	
	if(settings.autorotate) {
		setInterval(function(){
			if(mutex) {
				return;
			}
			if(this === elements[0]) {
				transit(false);
			}
			else {
				transit(true)
			}
		}, settings.autorotatespeed);
	}

    $(elements).each(function(i){
        $(elements[i]).animate(settings.states[i], settings.speed, 'swing', function(){ settings.ready = true })
        /*$(elements[1]).css({zIndex: 200});
        $(elements[2]).css({zIndex: 100}); 
		$(elements[0]).css({zIndex: 100});*/
        for (var j = 0; j<=lastEm;j++)
            $(elements[j]).css({zIndex: 1});
    });

    return this;
};