package WatorWorld;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

/**
 * A class to model a Shark in the Wator simulation.
 */
public class Shark extends Actor {
    
    // track base number of turns
    // for sharks before they can breed
    private static int standardBreedTime = 20;
    // track the base number of turns a shark
    // must eat within time or starve
    private static int standardStarveTime = 5;
    // track the total number of sharks
    private static int numSharks = 0;
    
    private static Random rand = new Random();
    
    private int turnsSinceLastAte;
    private int turnsUntilCanBreed;
    private int myBreedTime;
    private int myStarveTime;
    
    /**
     * Returns the current number of sharks.
     * @return the current number of sharks.
     */
    public static int getNumSharks(){
        return numSharks;
    }
    
    /**
     * Reset number of sharks to 0.
     */
    public static void resetNumSharks(){
        numSharks = 0;
    }
    
    /**
     * Change the base number of turns before sharks can breed
     * @param newBreedTime new number of turns. Must be > 0.
     */
    public static void setBreedTime(int newBreedTime){
        standardBreedTime = newBreedTime;
    }
    
    /**
     * Change the base number of turns a shark must eat
     * within or starve
     * @param newStarveTime new number of turns. Must be > 0
     */
    public static void setStarveTime(int newStarveTime){
        standardStarveTime = newStarveTime;
    }
    
    /**
     * 
     * @return The standard starve time for sharks.
     */
    public static int getStarveTime() {
        return standardStarveTime;
    }
    
    /**
     * 
     * @return The standard breed time for sharks.
     */
    public static int getBreedTime() {
        return standardBreedTime;
    }
    
    /**
     * 
     * @return The standard color for sharks.
     */
    public static Color getStandardSharkColor() {
        return Color.ORANGE;
    }
    
    /**
     * Create a new shark. Increment number of sharks that
     * exist by 1.
     */
    public Shark(){
        super();
        turnsSinceLastAte = 0;
        turnsUntilCanBreed = standardBreedTime;
        setColor(getStandardSharkColor());
        myBreedTime = standardBreedTime + rand.nextInt(10);
        myStarveTime = standardStarveTime + rand.nextInt(5);
        numSharks++;
    }
    
    /**
     * Check if starve then if not, act to move and breed
     * if time.
     * Sharks act by first checking if they starve.
     * Then they check if they can
     * move. If they can they move to a random location.
     * Then they check to see if it is time to breed.
     * If so then they create an offspring in an open
     * location if one exists. (Could be open due to 
     * eating or from moving.)
     */
    public void act(){
        // update turns alive and turns since last ate
        turnsUntilCanBreed--;
        turnsSinceLastAte++;
        
        boolean stillAlive = iDidNotStarve();
        
        if( stillAlive && !ate() )  
            tryMove();
        if(stillAlive)
            attemptToBreed();
    }
    
    private void attemptToBreed(){
        if(turnsUntilCanBreed <= 0){
            ArrayList<Location> openSpots = getGrid().getEmptyAdjacentLocations(getLocation());
            if(openSpots.size() > 0){
                Collections.shuffle(openSpots);
                Shark newShark = new Shark();
                newShark.putSelfInGrid(getGrid(), openSpots.get(0));
                turnsUntilCanBreed = myBreedTime;
            }  
        }
    }
    
    private boolean iDidNotStarve(){
        boolean result = true;
        if(turnsSinceLastAte == myStarveTime){
            removeSelfFromGrid();
            numSharks--;
            result = false;
        }    
        return result;
    }
    
    private void tryMove(){
        ArrayList<Location> openSpots = getGrid().getEmptyAdjacentLocations(getLocation());
        if(openSpots.size() > 0){
            Collections.shuffle(openSpots);
            moveTo(openSpots.get(0)); 
        }
    }
            
    private boolean ate(){
        ArrayList<Location> neighbors = getGrid().getOccupiedAdjacentLocations(getLocation());
        Collections.shuffle(neighbors);
        boolean eaten = false;
        int index = 0;
        while(!eaten && index < neighbors.size()){
            Actor possibleFood = getGrid().get(neighbors.get(index));
            if( possibleFood instanceof Fish){
                eaten = true;
                turnsSinceLastAte = 0;
                possibleFood.removeSelfFromGrid();
            }
            index++;
        }
        return eaten;
    }
    /**
     * Return the character for Sharks.
     */   
    public char getChar(){
        return 'S';
    }
}