/* *****************************************************************************
 *  Name:         Ibrahim Albluwi    
 *  NetID:        isma
 *  Precept:      P99
 *
 *  Description:    A generic data type representing a 2D grid of elements.
 *
 *  Exercise Steps: (a)   Complete the GridIterator class and test your
 *                        code using the given driver program.
 *
 *                  (b)   Implement a ColMajorIterator Iterator and then 
 *                        add code to main to test this iterator.
 *
 *                  (c)   Convert class Grid to an Iterable. Convert the while 
 *                        loop in the driver program for printing in
 *                        row-major order to a for-each loop.
 *
 *                  (c)   Add to main code that checks if all the elements
 *                        in the grid are distinct.
 **************************************************************************** */

import java.util.Iterator;
import java.util.NoSuchElementException;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdOut;


// A generic 2D grid of elements
public class Grid<Item> {

    private int n;          // the grid is of size n-by-n
    private Item[][] grid;  // a 2D array for holding items of any type


    // Creates an n-by-n grid
    public Grid(int n) {
        this.n = n;
        grid = (Item[][]) new Object[n][n];
    }


    // Sets the item at (row, col) in the grid to the given item
    public void set(int row, int col, Item item) {
        if (row < 0 || col < 0 || row >= n || col >= n)
            throw new IllegalArgumentException();
        grid[row][col] = item;
    }


    // Returns the item at (row, col) in the grid
    public Item get(int row, int col) {
       if (row < 0 || col < 0 || row >= n || col >= n)
            throw new IllegalArgumentException();
        return grid[row][col];
    }

    // Returns an instance of GridIterator
    public Iterator<Item> getGridIterator() {
        // ADD CODE HERE
    }


    // Allows iterating over the grid in row-major order 
    private class GridIterator implements ____________ {
        
        // ADD CODE HERE

        // creates a new iterator
        public GridIterator() {
            // ADD CODE HERE
        }

        // is there a next item in the iterator?
        public boolean hasNext() {
            // ADD CODE HERE
        }

        // this method is optional in the Iterator interface
        public void remove() {
            throw new UnsupportedOperationException();
        }

        // returns the next item in the iterator (and advances the iterator)
        public Item next() {
            if (!hasNext()) throw new NoSuchElementException();

            // ADD CODE HERE
        }
    }


    public static void main(String[] args) {
        int RANGE = 1000;

        // Create a size-by-size grid of Integers
        int size = Integer.parseInt(args[0]);
        Grid<Integer> myGrid = new Grid<Integer>(size);


        // Fill the grid with random numbers
        StdOut.println("2D Grid: ");
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                int rand = StdRandom.uniform(RANGE);
                StdOut.print(rand + "\t");
                myGrid.set(i, j, rand);
            }
            StdOut.println();
        }

        // Print the Grid contents in row-major order
        StdOut.print("In Row-Major: ");
        Iterator<Integer> iterator = myGrid.getGridIterator();
        while (iterator.hasNext()) {
            StdOut.print(" " + iterator.next());
        }
        StdOut.println();


        // (B)  ADD CODE TO PRINT IN COLUMN-MAJOR ORDER
        //      USE A WHILE LOOP


        // (D)  ADD CODE TO CHECK IF ALL ELEMENTS ARE DISTINCT
        //      USE A NESTED FOR-EACH LOOP
    }
}

