////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////

package pp.battleship.game.singlemode;

import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.model.Battleship;

/**
 * The {@code Copycat} class is a utility that creates a copy of a {@link ClientMessage}.
 * It implements the {@link ClientInterpreter} interface to interpret and process
 * different types of messages.
 */
class Copycat implements ClientInterpreter {
    private ClientMessage copiedMessage;

    /**
     * Creates a copy of the provided {@link ClientMessage}.
     *
     * @param msg the message to be copied
     * @return a copy of the provided message
     */
    static ClientMessage copy(ClientMessage msg) {
        final Copycat copycat = new Copycat();
        msg.accept(copycat, 0);
        return copycat.copiedMessage;
    }

    /**
     * Private constructor to prevent direct instantiation of {@code Copycat}.
     */
    private Copycat() { /* do nothing */ }

    /**
     * Handles the reception of a {@link ShootMessage}.
     * Since a {@code ShootMessage} does not need to be copied, it is directly assigned.
     *
     * @param msg  the received {@code ShootMessage}
     * @param from the identifier of the sender
     */
    @Override
    public void received(ShootMessage msg, int from) {
        // copying is not necessary
        copiedMessage = msg;
    }

    /**
     * Handles the reception of a {@link MapMessage}.
     * Creates a deep copy of the {@code MapMessage} by copying each {@link Battleship} in the message.
     *
     * @param msg  the received {@code MapMessage}
     * @param from the identifier of the sender
     */
    @Override
    public void received(MapMessage msg, int from) {
        copiedMessage = new MapMessage(msg.getShips().stream().map(Copycat::copy).toList());
    }

    /**
     * Creates a copy of the provided {@link Battleship}.
     *
     * @param ship the battleship to be copied
     * @return a copy of the provided battleship
     */
    private static Battleship copy(Battleship ship) {
        return new Battleship(ship.getLength(), ship.getX(), ship.getY(), ship.getRot());
    }
}
