/**
 * A rectangular array of integer
 *
 */
import java.util.*;

public class RectangularArrayV3
{
    private int       columns, rows;
    private ArrayList<Object> data;
    

    /**
     * Explicit Value Constructor
     *
     * @param rows    The number of rows
     * @param columbs The number of columns
     */
    public RectangularArrayV3(int rows, int columns)
    {
		if(rows < 0 || columns < 0) 
			throw new NegativeArraySizeException();
		else
		{
			this.rows = rows;
			this.columns = columns;
			this.data = new ArrayList<Object>();
			
			// since this is an array list, we must make each element as placeholders
			for (int ii = 0; ii < rows * columns; ii++)
			{
				data.add(null);
			}
		}

    }

    /**
     * Returns the number of columns in this RectangularArray
     *
     * @return   The number of columns
     */
    public int columns()
    {
		return this.columns;

    }
   /**
     * Get the element at a particular row and column
     *
     * @param row     The row index
     * @param column  The column index
     * @return        The int at the given row and column
     */
    public Object getElementAt(int row, int column)
    {
		return data.get(index(row, column));

    }

    /**
     * This implementation uses an ordinary array as the underlying
     * data structure.  This converts from row and column indexes
     * to an index into the underlying data structure.
     *
     * @param row     The row index
     * @param column  The column index
     * @return        The corresponding index in the data array
     */
    private int index(int row, int column) 
    {
		int idx;
		if (row >= this.rows || column >= this.columns ||
		 row < 0 || column < 0)
		 	throw new ArrayIndexOutOfBoundsException();
		else
			return (row * this.columns) + column;
    }
 
    /**
     * Returns the number of rows in this RectangularArray
     *
     * @return   The number of rows
     */
    public int rows()
    {
		return this.rows;
    }
    
    /**
     * Set the element at a particular row and column
     *
     * @param row     The row index
     * @param column  The column index
     * @param item    The integer to put in the array
     */
    public void setElementAt(int row, int column, Object item)
    {
		data.set(index(row, column), item);
    }
	
	/*
	 * return the String representation of this object
	 *
	 * @return A string with rows and columns based on the
	 *         the conceptual model
	 */
	public String toString ()
	{
		String builder;
		builder = "";
		
		for (int ii = 0; ii < rows * columns; ii++)
		{
			builder = builder + data.get(ii) + " ";
						
			// add new line if at the end of the row
			if ((ii % columns == columns - 1) && ii < data.size() - 1)
				builder = builder + "\n";
		}
		return builder;
	}

}
