LayoutMaker = Class.create();
LayoutMaker.prototype =
{

    initialize: function(container, padding)
    {
        this.container = container;
        this.padding = padding;
        this.allItems = $(this.container).childElements().filter(function(v) {return v.nodeType == 1 && v.tagName == "DIV" && v.hasClassName("item");});
    },

    layout: function()
    {
        function checkVisible(v)
        {
            return v.getStyle("display") !== "none";
        }
        this.items = this.allItems.filter(checkVisible); 
        this.analyzeItems();
        this.prepareEmptyLayout();
        this.doLayout();
        this.applyLayout();
    },

    analyzeItems: function()
    {
        var minWidth = null;
        var maxWidth = null;
        var padding = this.padding;
        for (var i = 0; i < this.items.length; i++)
        {
            var v = this.items[i];
            var itemWidth = v.getWidth() + padding * 2;
            if (minWidth === null || itemWidth < minWidth)
            {
                minWidth = itemWidth;
            }
            if (maxWidth === null || itemWidth > maxWidth)
            {
                maxWidth = itemWidth;
            }
            v.layoutWidth = itemWidth;
            v.layoutHieght = v.getHeight();
        }
        for (var i = 0; i < this.items.length; i++)
        {
            var v = this.items[i];
            var itemWidth = v.layoutWidth;
            if ((itemWidth % minWidth) !== 0)
            {
//                throw ("Invalid element getWidth: " + itemWidth + " Basic width is: " + minWidth + " Index: " + i);
            }
            v.layoutColumnSpan = Math.floor(itemWidth / minWidth);
        }
        var widestElementColumnSpan = maxWidth / minWidth;
        var numberOfColumns = Math.floor(this.container.getWidth() / minWidth); // ignore margings for now
        if (numberOfColumns < widestElementColumnSpan)
        {
            numberOfColumns = widestElementColumnSpan;

        }
        this.numberOfColumns = numberOfColumns;
        this.columnWidth = minWidth;
        this.widestItemColumnSpan = widestElementColumnSpan;
    },

    prepareEmptyLayout: function()
    {
        this.positions = [];
        var numberOfColumns = this.numberOfColumns;
        for (var i = 0; i < numberOfColumns; i++)
        {
            this.positions[i] =
            {
                bottom: 0,
                position: i
            };
        }
        for (var i = 0; i < this.items.length; i++)
        {
            var item = this.items[i];
            item.positioned = false;
            item.layoutColumn = null;
            item.layoutTop = null;
        }
    },

    doLayout: function()
    {

        var numberOfColumns = this.numberOfColumns;
        var positions = this.positions;

        function findBestPosition(item)
        {
            var bestPosition = null;
            for (var i = 0; i < numberOfColumns - item.layoutColumnSpan + 1; i++)
            {
                var position = positions[i];
                if (bestPosition === null || bestPosition.bottom > position.bottom)
                {
                    var currentBottom = position.bottom;
                    for (var j = position.position +1; j < position.position + item.layoutColumnSpan && j < numberOfColumns; j++)
                    {
                        var p = positions[j];
                        if (p.bottom > currentBottom)
                        {
                            currentBottom = p.bottom;
                            break;
                        }
                    }
                    if (bestPosition === null || bestPosition.bottom > currentBottom)
                    {
                        bestPosition = {position: position.position, bottom: currentBottom};
                    }
                }
            }
            if (bestPosition === null)
            {
                throw "layout error 1";
            }
            return bestPosition;
        }

        function allocatePosition(item, position)
        {
            item.positioned = true;
            item.layoutColumn = position.position;
            item.layoutTop = position.bottom;

            var newBottom = item.layoutTop + item.layoutHieght;

            for (var i = position.position; i < position.position + item.layoutColumnSpan; i++)
            {
                positions[i].bottom = newBottom;
            }
        }

        function positionItem(item)
        {
            var bestPosition = findBestPosition(item);
            allocatePosition(item, bestPosition);            
        }

        var maxBottom = 0;

        for (var i = 0; i < this.items.length; i++)
        {
            var item = this.items[i];
            positionItem(item);

            var bottom = item.layoutTop + item.layoutHieght;
            if (bottom > maxBottom)
            {
                maxBottom = bottom;
            }
        }

        this.maxBottom = maxBottom;
    },

    applyLayout: function()
    {
        var padding = this.padding;
        var heightSetter =  $('height-setter');
        if (heightSetter === null) {
            heightSetter = this.container;
        }
        heightSetter.setStyle(
        {
            height: this.maxBottom + "px"
        }
        );
        for (var i = 0; i < this.items.length; i++)
        {
            var item = this.items[i];
            item.setStyle(
            {
                top: item.layoutTop + "px",
                left: ((item.layoutColumn * this.columnWidth) + padding) + "px"
            });
        }
    }


}