import java.util.EnumMap;
import java.util.concurrent.ExecutionException;

/**
 * This class is cell of the board of the Gomoku game.
 */
public class GomokuCell{
    /** Enumerate neighbor with key in Cardinal direction and key representing the cell in that direction. */
    private EnumMap<Cardinal,GomokuCell> neighbour;
    /** The state of the cell represented by the enumerate Color, Nil is empty, white and black for the color of a token */
    private Color state; 

    //------------------Constructors--------------------------

    /**
     * The constructor of the cell.
     * @param state The state by default of the cell.
     */
    public GomokuCell(Color state){
        this.neighbour = new EnumMap<>(Cardinal.class);
        this.state = state;
    }

    //------------------Gets--------------------------

    /**
     * Return one neighbour.
     * @param car The Cardinal direction.
     * @return The GomokuCell at the direction.
     */
    public GomokuCell getNeighbour(Cardinal car){
        return this.neighbour.get(car);
    }
    
    /**
     * Return neighbours.
     * @return The EnumMap of neighbours.
     */
    public EnumMap<Cardinal, GomokuCell> getAllNeighbour(){
        return neighbour;
    }
    
    /**
     * Return the state.
     * @return The state of the current cell with one Color.
     */
    public Color getSate(){
        return this.state;
    }

    //------------------Sets--------------------------
    
    /**
     * Change state of the current cell.
     * @param c The color of the token played.
     * @throws IllegalStateException If the cell is not playable.
     */
    public void setState(Color c){
        if (!this.isPlayable())
            throw new IllegalStateException("This cell is not playable !" + this.toString());
        this.state = c;
    }
    

    //------------------Booleans--------------------------

    /**
     * This method returns if the current cell is empty
     * @return True if is empty, False if is not.
     */
    public boolean isEmpty(){
        return this.state == Color.NIL;
    }
    
    /**
     * This method returns if the cell has already played.
     * @return True if the cell is already played, False if is not.
     */
    public boolean isPlayed(){
        return !this.isEmpty();
    }
    
    /**
     * Return if the cell is playable.
     * @return True if the current cell can be played with the condition of the gomoku.
     */
    public boolean isPlayable(){
        for (Cardinal c : Cardinal.values()) {
            GomokuCell current = this.getNeighbour(c);
            if (current != null && current.isPlayed()) return true;
        }
        return false;
    }

    
    //------------------Methods--------------------------

    /**
     * This method link the cell at the Cardinal position on the current cell.
     * @param car The Cardinal direction of the cell to link.
     * @param cell The GomokuCell to link.
     */
    public void linkCell(Cardinal car, GomokuCell cell){
        this.neighbour.put(car, cell);
    }

    //------------------Overides--------------------------
    @Override
    public String toString() {
        switch (this.getSate()) {
            case Color.NIL:
                return " ";

            default:
                break;
        }
        return this.state.toString();
    }
}
