public abstract class Player {
    protected boolean myTurn;
    protected boolean isServer;
    protected boolean waitingForResponse;
    protected Player enemy; 
    protected String name;
    protected Board board;
    protected Boolean myCoin;
    protected boolean gameRunning;

    protected boolean sentCoin;

    protected boolean hasReceivedCoin;

    public Player() {
        this.setName("Player");
        this.hasReceivedCoin = false;
        this.sentCoin = false;
        this.myTurn = false;
        this.gameRunning = false;
    }

    /**
     * initialises this players board
     * @param size the size of the board to be created
     * @author Peer Ole Wachtel
     */
    public void createBoard(int size) {
        this.board = new Board(size);
    }

    public abstract void receiveShoot(Point point);

    public abstract
    void receiveHit(HitResponse hitResponse);

    public abstract void shoot(Point point);

    /**
     * only relevant for AI Players.
     * starts the first turn
     * @author Luca Conte
     */
    public void beginTurn() {
        System.out.println("issa my turn-a");
    }

    /**
     * sets the enemy Player
     * @author Peer Ole Wachtel
     */
    public void setEnemy(Player enemy) {
        this.enemy = enemy;
    }

    /**
     * sets the name of this player
     * @param name the name of this player
     * @author Luca Conte
     */
    public void setName(String name) {
        this.name = name;
    }
    /**
     * returns the name of this player
     * @return the name of this player
     * @author Luca Conte
     */
    public String getName() {
        return this.name;
    }

    /**
     * returns the board of this player
     * @return the board of this player
     * @author Lucas Bronson
     */
    public Board getBoard() {
        return this.board;
    }

    /**
     * marks the player as ready by sending their coin to the enemy player
     * calls determineCoinToss if the enemy coin has already been received
     * @author Luca Conte
     */
    public void ready() {
        this.enemy.receiveCoin(this.myCoin);
        this.sentCoin = true;
        if (hasReceivedCoin) {
            this.determineCoinToss();
        }
    };

    /**
     * determines the result of the coin toss
     * this method does nothing if either player is not ready yet or has not yet sent their coin
     * @author Luca Conte, Peer Ole Wachtel
     */
    protected void determineCoinToss() {
        if (!this.sentCoin || this.myCoin == null || !this.hasReceivedCoin || this.enemy.myCoin == null) return;
        boolean result = this.enemy.myCoin ^ this.myCoin; // XOR
        this.myTurn = result == this.isServer;
        if (this.myTurn) {
            this.beginTurn();
        }
        this.gameRunning = true;
        GameController.getMainFrame().refreshGameBoard();
    }

    /**
     * receives the coin toss from the enemy player
     * @param coin the coin of the enemy player
     * @author Peer Ole Wachtel
     */
    public abstract void receiveCoin(boolean coin);

    /**
     * returns whether the game this player is in has started, meaning both players are ready and have sent their coins
     * @return the game's running state
     * @author Luca Conte
     */
    public boolean isGameRunning() {
        return this.gameRunning;
    }

    /**
     * returns whether this player is ready and has sent their coin to the enemy player
     * @return the player's ready state
     */
    public boolean isReady() {
        return this.sentCoin;
    }

    /**
     * removes connections to the enemy and its board as well as setting myTurn and gameRunning to false
     * this stops the AI Players from making more moves and allows the garbage collector to remove the boards
     * and players
     * 
     * This method should be called at the end of a game
     * 
     * @author Luca Conte
     */
    public void destroy() {
        this.myTurn = false;
        this.gameRunning = false;
        this.board = null;
        this.enemy = null;
    }
}
