import java.util.ArrayList;

import edu.kzoo.grid.Grid;
import edu.kzoo.grid.Location;

/**
 * Write a description of class GravitationalPercolator here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class GravitationalPercolator extends GridObject
{
    // State (instance variables): all state is inherited from GridObject.

    // Constructor(s):

    /** Constructs a percolator that percolates down, left, and right, but
     *  not up.
     */
    public GravitationalPercolator()
    {
        // Initialize the GridObject aspects of this VerticalPercolator.
        super();
    }

    // Redefined method from GridObject:

    /** Acts (percolates) for one step in the percolation simulation.
     */
    public void act()
    {
        Debug.println("Percolator " + location() + " about to act...");
        ArrayList<Location> percolationLocations = getPercolationLocations();
        for ( Location loc : percolationLocations )
            percolateTo(loc);
    }

    /** Gets the locations to which to percolate.
     *  Since a gravitational percolator percolates everywhere but up,
     *  this method gets the locations to the left, right, and below
     *  the current location and adds them to the list.
     *  (Precondition: this percolator object is in a grid.)
     */
    protected ArrayList<Location> getPercolationLocations()
    {
        // Get partial list with single location below the current location.
        ArrayList<Location> locs = new ArrayList<Location>();

        // Get the location below the current location and put it in the list.
        int currentRow = location().row();
        int currentCol = location().col();
        locs.add(new Location(currentRow+1, currentCol));

        // Get the location to the left of the current location and put it in the list.
        locs.add(new Location(currentRow, currentCol-1));

        // Get the location to the right of the current location and put it in the list.
        locs.add(new Location(currentRow, currentCol+1));

        return locs;
    }

    /** Percolates (spreads) to a specified new location, if possible.
     *  This method checks to see whether the new location is in the
     *  grid and is empty, and, if so, percolates to that location.  If
     *  the new location is not a valid, empty location, this method
     *  does nothing; in other words, the substance will not percolate.
     *  (Precondition: this object is in a grid and <code>newLoc</code>
     *  is not null.)
     *  @param  newLoc    new location value
     *  @throws       IllegalArgumentException if the precondition is not met
     */
    protected void percolateTo(Location newLoc)
    {
        // If newLoc is not in the grid or is not empty, do nothing.
        if ( ! grid().isEmpty(newLoc) )
            return;

        // If newLoc is a valid, empty location, spread to that location.
        GridObject dupl = duplicate();
        grid().add(dupl, newLoc);
        PercolationController.getController().notePercolationTo(dupl);
    }

    /** Creates a duplicate of this percolator.
     */
    protected GridObject duplicate()
    {
        return new GravitationalPercolator();
    }
}
