Show:
/* Copyright © 2015-2016 David Valdman */

define(function(require, exports, module){
    var View = require('../core/View');
    var FlexLayout = require('./FlexLayout');

    /**
     * A layout that arranges items in a grid and can rearrange the grid responsively.
     *
     *  The user provides the number of items per row in an array or a dictionary
     *  with keys that are pixel values. The items will be sized to fill the available space.
     *
     *  @class GridLayout
     *  @constructor
     *  @extends Core.View
     *  @param [options] {Object}                           Options
     *  @param [options.spacing=0] {Array}                  Gap space between successive rows and columns
     */
    var GridLayout = View.extend({
        defaults : {
            spacing : [0, 0]
        },
        initialize : function initialize(options){
            this.rows = [];
            this.col = new FlexLayout({
                direction: FlexLayout.DIRECTION.Y,
                spacing: options.spacing[1]
            });

            this.add(this.col);
        },
        push : function(item, flex, row){
            if (row > this.rows.length) return;

            if (row === -1){
                this.unshift(item, flex, row);
                return;
            }

            if (row === undefined) row = this.rows.length;

            var flexRow;
            if (row === this.rows.length){
                // append a new row
                flexRow = new FlexLayout({
                    direction: FlexLayout.DIRECTION.X,
                    spacing: this.options.spacing[0]
                });

                this.rows.push(flexRow);
                this.col.push(flexRow, 1);
            }
            else flexRow = this.rows[row];

            flexRow.push(item, flex);
        },
        pop : function(row){
            if (row === undefined) row = this.rows.length - 1;

            var flexRow = this.rows[row];

            var item = flexRow.pop();

            if (flexRow.length() === 0)
                removeRow.call(this, row);

            return item;
        },
        unshift : function(item, flex, row){
            if (row < -1) return;

            if (row === this.rows.length){
                this.push(item, flex, row);
                return;
            }

            if (row === undefined) row = -1;

            var flexRow;
            if (row === -1){
                // prepend a new row
                flexRow = new FlexLayout({
                    direction : FlexLayout.DIRECTION.X,
                    spacing : this.options.spacing[0]
                });

                this.rows.unshift(flexRow);
                this.col.unshift(flexRow, 1);
            }
            else flexRow = this.rows[row];

            flexRow.unshift(item, flex);
        },
        shift : function(row){
            if (row === undefined) row = 0;
            var flexRow = this.rows[row];

            var item = flexRow.shift();

            if (this.rows[row].length() === 0)
                removeRow.call(this, row);

            return item;
        },
        insertAfter : function(row, col, item, flex){
            var flexRow = this.rows[row];
            flexRow.insertAfter(col, item, flex);
        },
        insertBefore : function(row, col, item, flex){
            var flexRow = this.rows[row];
            flexRow.insertBefore(col, item, flex);
        },
        unlink : function(row, col){
            var flexRow = this.rows[row];
            flexRow.unlink(col);
        },
        advance : function(row){
            var nextRow = row + 1;

            var numRows = this.rows.length;

            var surface = this.pop(row);
            surface.remove();

            nextRow -= (numRows - this.rows.length);

            var flex = 1;
            this.unshift(surface, flex, nextRow);
        },
        retreat : function(row){
            var prevRow = row - 1;

            var surface = this.shift(row);
            surface.remove();

            var flex = 1;
            this.push(surface, flex, prevRow);
        },
        resize : function(colsPerRow){
            for (var row = 0; row < colsPerRow.length; row++){
                var nCols = colsPerRow[row];
                var count = this.rows[row].nodes.length;

                while (count > nCols) {
                    this.advance(row);
                    count--;
                }

                while (count < nCols) {
                    this.retreat(row + 1);
                    count++;
                }
            }
        }
    });

    function removeRow(rowIndex){
        var emptyRow = this.col.unlink(this.rows[rowIndex]);
        emptyRow.remove();
        this.rows.splice(rowIndex, 1);
    }

    module.exports = GridLayout;
});