# graphics/grid.js

    'use strict';

    /**
     * @class Grid
     * @param {rows} rows - Number of rows in the grid.
     * @param {cols} cols - Number of cols in the grid.
     */
    function Grid(rows, cols) {
        this.grid = new Array(rows);
        for (var i=0; i < rows; i++) {
            this.grid[i] = new Array(cols);
        }
    }

    /**
     * Initializes a Grid from an array.
     * @param {array} arr - Array containing elements to be made into a Grid.
     */
    Grid.prototype.initFromArray = function(arr){
        for(var i = 0; i < arr.length; i++){
            for(var j = 0; j < arr[0].length; j++){
                if (this.inBounds(i, j)) {
                    this.set(i, j, arr[i][j]);
                }
            }
        }
    };

    /**
     * Initializes the contents of the grid with `value`.
     * @param {number|string|object} value - The value to be inserted in all
     * positions of the grid.
     */
    Grid.prototype.init = function(value) {
        for (var i = 0; i < this.numRows(); i++) {
            for (var j = 0; j < this.numCols(); j++) {
                this.grid[i][j] = value;
            }
        }
    };

    /**
     * Gets the object stored at the requested row and column.
     * @param {number} i - The row of the desired object.
     * @param {number} j - The col of the desired object.
     * @returns {object} The object stored in the grid at that position.
     */
    Grid.prototype.get = function(i, j) {
        return this.grid[i][j];
    };

    /**
     * Sets an object at the requested row and column.
     * @param {number} i - The row of the destination of the object.
     * @param {number} j - The row of the destination of the object.
     */
    Grid.prototype.set = function(i, j, value) {
        this.grid[i][j] = value;
    };

    /**
     * Returns the number of rows in the grid.
     * @returns {number} The number of rows in the grid.
     */
    Grid.prototype.numRows = function() {
        return this.grid.length;
    };

    /**
     * Returns the number of cols in the grid.
     * @returns {number} The number of cols in the grid.
     */
    Grid.prototype.numCols = function() {
        return this.grid[0].length;
    };

    /**
     * Checks whether the given row and col exist in the grid.
     * @param {number} row - Row of the position being checked.
     * @param {number} col - Col of the position being checked.
     * @param {boolean} Whether or not the given position is in bounds.
     */
    Grid.prototype.inBounds = function(row, col) {
        if(row < 0 || col < 0){
            return false;
        }
        if(row >= this.numRows() || col >= this.numCols()){
            return false;
        }
        return true;
    };

    /**
     * Converts a grid to a list.
     * For example:
     * -------
     * A B C D
     * E F G H
     * I J K L
     * -------
     * would convert to:
     * -------
     * [[0, 0, 'A'], [0, 1, 'B'], [0, 2, 'C'], [0, 3, 'D'], [1, 0, 'E']...[2, 3, 'L']]
     * @returns {array} List representation of the Grid.
     */
    Grid.prototype.toList = function() {
        var list = [];
        for (var i = 0; i < this.grid.length; i++) {
            for (var j = 0; j < this.grid[0].length; j++) {
                var value = this.grid[i][j];
                if (value && value !== 0) {
                    list.push([i, j, value]);
                }
            }
        }
        return list;
    };

    /**
     * Generates a string representation of the Grid.
     * @returns {string} A representatino of a grid of the format
     * "A B C <br/>D E F <br/>G H I <br/>"
     */
    Grid.prototype.toString = function() {
        var result = "";
        for(var i = 0; i < this.numRows(); i++){
            for(var j = 0; j < this.numCols(); j++){
                result += this.get(i, j) + " ";
            }
            result += "<br/>";
        }
        return result;
    };

    module.exports = Grid;