(function($) {
    $.fn.flow = function(method) {
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.flow' );
        }
    };
        
    var methods = {
        init : function(options) {
            var settings = $.extend({
                'pinsContainer'     : '#pinboard',
                'pinSelector'       : '.pin',
                'columnCount'       : 3,
                'columnWidthInner'  : 150,
                'columnMargin'      : 10,
                'columnPadding'     : 0
            }, options);

            var self = this;
            $(window).load(function() {
                methods.allPins(self, settings);
            });
        },
        
        allPins : function(elem, options) {
            var contentArea = $(options.pinsContainer).width();
            console.log(contentArea);
            
            this.columnWidthOuter = options.columnWidthInner + options.columnMargin + options.columnPadding;
            this.columns = Math.max(options.columnCount, parseInt(contentArea / this.columnWidthOuter));
            var columnContainerWidth = (this.columnWidthOuter * this.columns) - options.columnMargin;
            
            for (var i = 0; i < this.columns; i++) {
                this.pinArray[i] = 0;
            }

            // Find all pins
            var pins = $(options.pinsContainer + ' ' + options.pinSelector);
            
            this.flowPins(elem, pins, options);
        },
        
        flowPins : function(elem, pins, options) {
            // Place each pin in the column that is the shortest at that pin's turn
            for (i=0; i < pins.length; i++) {
    
                // Get the current pin
                var pin = pins[i];
    
                // Find the index of the smallest value in the array
                var shortestColumn = jQuery.inArray((Math.min.apply(Math, this.pinArray)), this.pinArray);
                var shortestColumnTop = this.pinArray[shortestColumn];
    
                // Assign the pin's "top:" and "left:" values based on the current column
                pin.style.top = shortestColumnTop + "px";
                pin.style.left = (shortestColumn * this.columnWidthOuter) + "px";
    
                // Change the current column's height to include the height of the newly added pin
                this.pinArray[shortestColumn] = shortestColumnTop + pin.offsetHeight + options.columnMargin;
            }
            
            elem.height(Math.max.apply(Math, this.pinArray) + 'px');
            this.showPins(options);
        },
        
        showPins : function(options) {
            if (!($.browser.msie && parseInt($.browser.version) == 7)) {
                $(options.pinsContainer).animate({opacity:'1'}, 300);
            }
        },
        
        pinArray : [],
        columns  : 0,
        columnWidthOuter     : 0,
        columnContainerWidth : 0
    };

})(jQuery);
