(function($) {
    $.fn.layoutRects = function(options) {
        var defaults = {
            paddingWidth: 24,
            paddingHeight: 24,
            containerLeft: 0,
            containerHeight: null, // from offset().top to bottom of window
            handler: null
        };

        var opts = $.extend(defaults, options);

        var container = this;

        var laneWidth;

        var widestInColumn;
        var currentLeft;
        var currentTop;
        var canvasHeight = opts.containerHeight;

        resetCanvas();

        // A simple greedy algorithm for placing bits
        function layout(items) {
            if (!opts.containerHeight) {
                canvasHeight = $(window).height() - Math.floor(container.offset().top);
            }

            for (var i = 0; i < items.length; ++i) {
                var item = items[i];
                var template = opts.handler(item);

                var left = currentLeft + opts.paddingWidth;
                var top = currentTop + opts.paddingHeight;

                var remainingHeight = canvasHeight - currentTop - opts.paddingHeight;

                var height = Math.ceil(item.height);
                if (height < remainingHeight) {
                    currentTop += height + opts.paddingHeight;
                } else {
                    currentLeft += (widestInColumn + opts.paddingWidth);
                    currentTop = height + opts.paddingHeight;

                    left = currentLeft + opts.paddingWidth;
                    top = opts.paddingHeight;

                    widestInColumn = 0;
                }

                if (item.width > widestInColumn)
                    widestInColumn = item.width;

                placeItem(template, item, left, top);
            }
        }

        function placeItem(template, item, left, top) {
            template.attr("id", item.id);
            template.css("position", "absolute");
            template.css("left", left);
            template.css("top", top);
            template.appendTo(container);
        }

        function resetCanvas() {
            var keep = $(".keepme", container);
            container.empty();
            container.append(keep);

            laneWidth = $(document).width() - opts.containerLeft;

            widestInColumn = 0;
            currentLeft = 0;
            currentTop = 0;
        }

        function resizeCanvas() {
            var contentsWidth = currentLeft + widestInColumn + (opts.paddingWidth * 2);
            $("#memo-lane").width(Math.max(contentsWidth, laneWidth));
            $("#memo-lane").height(canvasHeight);
        }

        return {
            update: function(memories) {
                layout(memories);
                resizeCanvas();
                return this;
            },

            reset: function() {
                resetCanvas();
                return this;
            }
        }
    }
})(jQuery);


