/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Cay Horstmann
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 */

import info.gridworld.actor.Actor;
import info.gridworld.actor.Bug;
import info.gridworld.actor.Flower;
import info.gridworld.grid.Grid;
import info.gridworld.grid.Location;

import java.util.ArrayList;

public class LifeBug extends Bug
{

    // This constructor is technically unnecessary, but it clearly conveys the
    // intent to have a default constructor.
    public LifeBug()
    {
        super();
    }

    /**
     * Moves to the next location of the square.
     */
    public void act()
    {
        double probBreed = 1.0 / 7;
        double probDeath = 1.0 / 5;

        if (Math.random() < probBreed) {
            breed();
        } else {
            super.act();
        }
        
        if (Math.random() < probDeath) {
            die();
        }

        //            if (Math.random() < probDeath) {
        //                die();
        //            }
    }
    
    public void die() {
        removeSelfFromGrid();
    }

    /**
     * Tests whether this bug can move forward into a location that is empty or
     * contains a flower.
     * @return true if this bug can move.
     */
    public boolean canMove()
    {
        Grid<Actor> gr = getGrid();
        if (gr == null)
            return false;
        Location loc = getLocation();
        for (int dir = getDirection()+Location.LEFT; 
                dir <= getDirection()+Location.HALF_CIRCLE; 
                dir += Location.RIGHT) {
            Location next = loc.getAdjacentLocation(dir);
            if (gr.isValid(next)) {
                Actor neighbor = gr.get(next);
                if (neighbor == null || neighbor instanceof Flower) return true;
            }
        }
        return false;
        // ok to move into empty location or onto flower
        // not ok to move onto any other actor
    }

    /**
     * Turns the bug 90 degrees to the right without changing its location.
     */
    public void turn()
    {
        setDirection(getDirection() + Location.RIGHT);
    }

    /**
     * Moves the bug forward, putting a flower into the location it previously
     * occupied.
     */
    public void move()
    {
        Grid<Actor> gr = getGrid();
        ArrayList<Location> locs = new ArrayList<Location>();
        ArrayList<Integer> dirs = new ArrayList<Integer>();

        if (gr == null)
            return;
        Location loc = getLocation();
        for (int dir = getDirection()+Location.LEFT; 
                dir <= getDirection()+Location.RIGHT; 
                dir += Location.RIGHT) {
            Location next = loc.getAdjacentLocation(dir);

            if (gr.isValid(next)) {
                Actor neighbor = gr.get(next);
                if (neighbor == null || neighbor instanceof Flower) {
                    locs.add(next);
                    dirs.add(dir);
                }
            }
        }

        if (locs.size() == 0) {
            return;
        }

        // Do not cast Math.random() as an int.  Ever.
        // Choose a direction in which to move and move!
        int randomSelection = (int) (Math.random() * locs.size());
        Location next = locs.get(randomSelection);
        if (gr.isValid(next)) {
            setDirection(dirs.get(randomSelection));
            moveTo(next);
        } else {
            removeSelfFromGrid();
        }
        Flower flower = new Flower(getColor());
        flower.putSelfInGrid(gr, loc);
    }


    /**
     * Checks for adjacent locations and places new LifeBugs on all empty ones
     */
    public void breed() {
        Grid<Actor> gr = getGrid();
        if (gr == null)
            return;
        Location loc = getLocation();
        for (int dir = Location.NORTH; dir < Location.FULL_CIRCLE; dir+= Location.RIGHT) {
            Location next = loc.getAdjacentLocation(dir);            
            if (!gr.isValid(next))
                return;
            Actor neighbor = gr.get(next);
            // Question: WHY IS THIS NEXT COMPARISON NOT .equals()?
            // Answer: Because if neighbor is null, it cannot do any methods
            if (neighbor == null) {
                //            if (neighbor == null || neighbor instanceof Flower) {
                LifeBug baby = new LifeBug();
                baby.setColor(getColor());
                baby.putSelfInGrid(gr, next);
                baby.setDirection(getDirection());
            }
        }
    }
}