/******************************* FILE HEADER **********************************
    File:        Fish.java
    Main Class:  Aquarium.java
    
    Author:      James D. Skrentny
                 copyright 2000, all rights reserved
    Course:      CS302: Lectures 1 & 2
    
    Compiler:    CodeWarrior IDE 4.0 (JDK 1.2)
    Platform:    Windows NT 4.0
 **************************** 80 columns wide *********************************/

import java.awt.Color;

/** 
 * Represents a Fish.
 * 
 * Bugs: None known.
 **/ 
 
class Fish {           
           
    private int    foodPoints; // fish's energy, 0 to Tank.FISH_MAX_POINTS
    private Location location; // fish's Location in the tank
    private boolean direction; // fish's heading, Tank.RIGHT or Tank.LEFT


    /** 
     * Constructs a new Fish at a random Location and randomly facing either
     * in the left or right direction.
     **/
    public Fish ( ) {           
        foodPoints = Tank.FISH_MAX_POINTS;
        location   = new Location((int)(Math.random()*Tank.TANK_WIDTH   + 1), 
                                  (int)(Math.random()*Tank.WATER_HEIGHT + 1));
        direction  = (int) (Math.random()*2) == 0 ? Tank.RIGHT : Tank.LEFT;
    }           


    /**
     * Returns the Location of this Fish.
     *
     * @return this fish's Location
     **/
    public Location getLocation () {           
        return location;
    }           


    /**
     * Get the Color of this Fish.
     * A weak fish is white, otherwise it's pink.
     *
     * @return this fish's Color
     **/
    public Color getColor () {           
        if (isWeak()) return Color.white;
        else          return Color.pink;
    }           


    /**
     * Get the direction of this Fish
     *
     * @return this fish's direction
     **/
    public boolean getDirection () {           
        return direction;
    }           


    /**
     * Get the number of food points of this Fish.
     *
     * @return this fish's food points
     **/
    public int getFoodPoints () {           
        return foodPoints;
    }           


    /**
     * Determine is this Fish is alive.
     *
     * @return true if this fish is alive, false otherwise
     */
    public boolean isAlive () {           
        return foodPoints > 0;
    }           


    /**
     * Determine if this Fish is dead.
     *
     * @return true if this fish is dead, false otherwise
     */
    public boolean isDead () {           
        return !isAlive();
    }          


    /**
     * Determine is this Fish is weak.
     *
     * @return true if this fish is weak, false otherwise
     */
    public boolean isWeak () {           
        return foodPoints < Tank.FISH_MAX_POINTS*Tank.STRENGTH_THRESHOLD;
    }           


    /**
     * Move this fish, if living, one step from its current location, but it
     * can't move backwards.
     **/
    public void move ( ) {           
        if (isAlive()) {
            int x = location.getX();   // fish's current x-coord
            int y = location.getY();   // fish's current x-coord
        
           // change directions if at wall
            if ( ((x <= 0) && (direction == Tank.LEFT)) 
              || ((x >= Tank.TANK_WIDTH) && (direction == Tank.RIGHT)) ) 
            
            {
                direction = !direction;
            }
            else {  
                // Simple Move Algorithm:
                //    randomly choose a move until a valid move is found
                // This isn't a very efficient moving algorithm (we may have
                // to choose a lot of moves if the fish is in a corner), but 
                // it is easy to code.
                boolean invalidMove = true; // true iff a valid move found
                int dx, dy; //change in x and y coordinates
                do {
                    // randomly choose a change of location
                    switch ((int)(Math.random()*5)) {   // 5 ways to move
                        case 0:  dx = 0; dy =  1; break; // straight down
                        case 1:  dx = 1; dy =  1; break; // diagonal down 
                        case 2:  dx = 1; dy =  0; break; // straight across
                        case 3:  dx = 1; dy = -1; break; // diagonal up
                        default: dx = 0; dy = -1; break; // straight up
                    }
        
                    // if facing left, make dx negative
                    if (direction == Tank.LEFT) {
                        dx = -dx;
                    }
                    
                    // compute new coordinates
                    int newX = x + dx;
                    int newY = y + dy;
                    
                    // check if new location is valid
                    if ((newX >= 0) && (newX <= Tank.TANK_WIDTH) &&
                        (newY >= 0) && (newY <= Tank.WATER_HEIGHT)) {
                          invalidMove = false;
                    }
                } while (invalidMove);
            
                // move Fish
                location.move(dx, dy);
            }
            // decrement foodPoints
            foodPoints -= Tank.FISH_MOVE_COST;
        }        
    }           


    /**
     * This Fish attempts to eat at the specified FoodCenter.
     *
     * @param fc the specified food center
     **/
    public void eat (FoodCenter fc) {           
        if (isAlive()) {
            int amountEaten = fc.foodWanted(Tank.FISH_MAX_POINTS - foodPoints);
            foodPoints += amountEaten;
        }
    }           


    /**
     * Kills the Fish because it was eaten by a piranha.
     **/
    public void gotEatten () {           
        foodPoints = 0;
    }           


    /**
     * Get the information about this Fish.
     *
     * @return a String representation of this fish
     **/
    public String toString () {           
        String info = "Fish ";

        if (isAlive()) {
            info += "  Direction: ";
            if (direction == Tank.RIGHT) info += "Right";
            else                         info += "Left";
            info += "  Location: "    + location;
            info += "  Food points: " + foodPoints;
        }
        else {
            info += " is dead";
        }

        return info;
    }           
           
}           
