(function($) {
    //var ITEM_SIZE;
    var ITEM_RECTS;
    var CAROUSEL_WIDTH;
    var CAROUSEL_HEIGHT;
    var ITEMS;
    var MIN_ITEMS = 6;
    var CAROUSEL_ID;

    var _selectedIndex = -1;
    var _settings;

    function setupVars(ref, settings) {
        _settings = $.extend({
            items: ref.find("a") //$("#carousel a")
            //itemSize: 256
        },
        settings || {});

        CAROUSEL_ID = ref.parent().attr("id");
        ITEMS = new Array();

        _settings.items.each(function() {
            var new_item = new Object();
            new_item.title = $(this).find(".title:first").text();
            new_item.description = $(this).find(".description:first").text();
            new_item.url = $(this).attr("href");
            new_item.image = $(this).find("img:first").attr("src");
            new_item.originalHeight = $(this).find("img:first").height();
            new_item.originalWidth = $(this).find("img:first").width();

            ITEMS.push(new_item);
        });

        //ITEM_SIZE = _settings.itemSize;
        CAROUSEL_WIDTH = ref.width();
        CAROUSEL_HEIGHT = ref.height();
        ITEM_RECTS = preCalculateRects(ITEMS.length);
    }

    $.fn.carousel = function(settings) {
        var refCarousel = $(this);
        setupVars(refCarousel, settings);

        // Add items
        for (var i = 0; i < ITEMS.length; i++) {
            // Create item
            var wrapper = createItem(i);

            // Click event handler
            wrapper.click(function(event) {
                var newIndex = $(this).attr("itemIndex");
                if (newIndex == _selectedIndex) {
                    // Navigate to item
                }
                else {
                    doSelection(newIndex);

                    event.preventDefault();
                }

            });

            refCarousel.append(wrapper);
        }

        $(this).removeClass("loading");
        // First time animation
        doSelection(0);
        return this;
    };

    function doSelection(index) {
        beforeSelectionStarts();

        _selectedIndex = index;

        layout(index);
    }

    function showProjectInfo() {
        $("#" + CAROUSEL_ID + " .item-title").attr("href", ITEMS[_selectedIndex].url);
        $("#" + CAROUSEL_ID + " .item-title").html(ITEMS[_selectedIndex].title);

        $("#" + CAROUSEL_ID + " .item-description").text(ITEMS[_selectedIndex].description);
    }

    function beforeSelectionStarts() {
        if (_selectedIndex != -1) {
            $("#item_" + _selectedIndex).removeClass("item-selected");
        }
    }

    function selectionCompleted(wrapper) {
        showProjectInfo();
        wrapper.addClass("item-selected");
    }

    function preCalculateRects(count) {
        var rectList = new Array();
        for (var i = 0; i < count; i++) {
            var rect = calculateRect(i, count);
            rectList.push(rect);
        }

        return rectList;
    }

    function createItem(index) {
        var img = $("<img src='" + ITEMS[index].image + "' />");
        img.attr("itemIndex", index);
        var wrapper = $("<a id='item_" + index + "' class='carousel-link' href='" + ITEMS[index].url + "'/>").append(img);
        wrapper.attr("title", ITEMS[index].title);
        //wrapper.attr("originalHeight", ITEMS[index].originalHeight);
        //wrapper.attr("originalWidth", ITEMS[index].originalWidth);

        // Store index of item
        wrapper.attr("itemIndex", index);
        wrapper.hover(
			  function() {
			      $(this).addClass("highlightItem");
			      var theimage = $(this).find("img:first");
			      theimage.attr("old-opacity", theimage.css("opacity"));
			      theimage.css("opacity", 1);
			  },
			  function() {
			      $(this).removeClass("highlightItem");
			      var theimage = $(this).find("img:first");
			      theimage.css("opacity", theimage.attr("old-opacity"));
			  }
			);

        return wrapper;
    }

    function calculateRect(index, count) {
        var old_count = count;

        if (count < MIN_ITEMS) {
            count = MIN_ITEMS;
        }

        count = count + Math.floor(count / 10);

        if (count % 2 == 1) {
            count = count + 1;
        }



        if (index / old_count > .5) {
            index = index + (count - old_count);
        } else if (index / old_count == .5) {
            index = Math.round(count / 2);
        }

        var ratio = (index / count);
        var newratio = (((Math.sin(ratio * Math.PI) - 1) * (Math.cos(ratio * Math.PI) / Math.abs(Math.cos(ratio * Math.PI)))) + 1) / 2
        //ratio = newratio;

        //var itemWidth = ITEM_SIZE;
        //var itemHeight = ITEM_SIZE;

        //var x = ((CAROUSEL_WIDTH - itemWidth) * 0.5) * Math.sin(newratio * 2 * Math.PI);
        var x = Math.sin(newratio * 2 * Math.PI);
        var y = Math.sin(-1 * Math.PI + Math.PI * newratio) + 1;
        var scale = Math.sin(-1 * Math.PI + Math.PI * ratio) * .8 + 1;
        var opacity = Math.sin(-1 * Math.PI + Math.PI * newratio) * .75 + 1;

        var rect = new Object();
        //rect.width = itemWidth * scale ;
        //rect.height = itemHeight * scale;
        rect.scale = scale;
        rect.opacity = opacity;
        rect.x = x; //(CAROUSEL_WIDTH - rect.width) * 0.5 + x;
        rect.z = Math.floor(count * y * 100);
        rect.y = y; //* (CAROUSEL_HEIGHT - rect.height);

        return rect;
    }

    function layout(selectedIndex) {
        var itemCount = ITEMS.length;
        for (var i = 0; i < itemCount; i++) {
            // Get the rect to be used
            var rectIndex = i - selectedIndex;
            if (rectIndex < 0) {
                rectIndex += ITEMS.length;
            }

            var rect = ITEM_RECTS[rectIndex];

            var wrapper = $("#item_" + i);
            wrapper.css("zIndex", rect.z);
            var img = wrapper.find("img:first");

            // Animate
            var newWidth = Math.round(ITEMS[i].originalWidth * rect.scale); //wrapper.attr("originalWidth") * rect.scale;
            var newHeight = Math.round(ITEMS[i].originalHeight * rect.scale);  //wrapper.attr("originalHeight") * rect.scale;
            var newLeft = Math.round((CAROUSEL_WIDTH - newWidth) * 0.5 + rect.x * (CAROUSEL_WIDTH - newWidth) * 0.5);
            var newTop = Math.round(rect.y * (CAROUSEL_HEIGHT - newHeight));
            //alert("y: "+ rect.y + " height: " + newHeight + " top: " + newTop);

            wrapper.animate({
                left: newLeft,
                top: newTop,
                width: newWidth,
                height: newHeight
            },
			{ complete: function() {
			    var index = $(this).attr("itemIndex");

			    if (index == _selectedIndex) {
			        selectionCompleted($(this));
			    }
			} 
			});

            img.animate({
                width: newWidth,
                height: newHeight,
                opacity: rect.opacity
            },
			{ complete: function() {
			    var index = $(this).attr("itemIndex");

			    if (index == _selectedIndex) {
			        $(this).removeAttr("old-opacity").css("opacity", 1);
			    }
			} 
			});
        }
    }

})(jQuery);

