package legion.muyue.best2048.data;

import com.google.gson.annotations.SerializedName;
import java.util.Arrays;

/**
 * Représente l'état complet d'une partie du jeu 2048 à un instant T.
 * Cette classe est typiquement utilisée pour encapsuler les données reçues
 * en réponse à une requête d'état de jeu, souvent via JSON (Gson).
 * Elle contient les informations sur le plateau, les scores, le joueur courant, etc.
 */
public class GameStateResponse {

    /**
     * L'identifiant unique de la partie.
     * Utilisé par Gson pour la sérialisation avec le nom "gameId".
     */
    @SerializedName("gameId")
    private String gameId;

    /**
     * La grille de jeu actuelle, représentée par un tableau 2D d'entiers.
     * Chaque entier représente la valeur d'une tuile (0 pour une case vide).
     * Utilisé par Gson pour la sérialisation avec le nom "board".
     */
    @SerializedName("board")
    private int[][] board;

    /**
     * Le score actuel du joueur 1.
     * Utilisé par Gson pour la sérialisation avec le nom "player1Score".
     */
    @SerializedName("player1Score")
    private int player1Score;

    /**
     * Le score actuel du joueur 2.
     * Utilisé par Gson pour la sérialisation avec le nom "player2Score".
     */
    @SerializedName("player2Score")
    private int player2Score;

    /**
     * L'identifiant du joueur dont c'est actuellement le tour de jouer.
     * Utilisé par Gson pour la sérialisation avec le nom "currentPlayerId".
     */
    @SerializedName("currentPlayerId")
    private String currentPlayerId;

    /**
     * Indicateur booléen signalant si la partie est terminée.
     * Utilisé par Gson pour la sérialisation avec le nom "isGameOver".
     */
    @SerializedName("isGameOver")
    private boolean isGameOver;

    /**
     * L'identifiant du joueur gagnant, si la partie est terminée et qu'il y a un gagnant.
     * Peut être null si la partie n'est pas terminée ou s'il y a égalité.
     * Utilisé par Gson pour la sérialisation avec le nom "winnerId".
     */
    @SerializedName("winnerId")
    private String winnerId;

    /**
     * Le statut global de la partie (par exemple, "en cours", "terminée").
     * Utilisé par Gson pour la sérialisation avec le nom "status".
     */
    @SerializedName("status")
    private String status;

    /**
     * L'identifiant du joueur 1.
     * Utilisé par Gson pour la sérialisation avec le nom "player1Id".
     */
    @SerializedName("player1Id")
    private String player1Id;

    /**
     * L'identifiant du joueur 2.
     * Utilisé par Gson pour la sérialisation avec le nom "player2Id".
     */
    @SerializedName("player2Id")
    private String player2Id;

    /**
     * Le score cible à atteindre pour gagner la partie (par exemple, 2048).
     * Utilisé par Gson pour la sérialisation avec le nom "targetScore".
     */
    @SerializedName("targetScore")
    private int targetScore;


    /**
     * Constructeur par défaut.
     * Nécessaire pour certaines bibliothèques de sérialisation/désérialisation comme Gson.
     */
    public GameStateResponse() {
        // Constructeur par défaut explicite
    }

    /**
     * Récupère l'identifiant unique de la partie.
     *
     * @return L'identifiant de la partie.
     */
    public String getGameId() { return gameId; }

    /**
     * Récupère la grille de jeu actuelle.
     * Le tableau retourné est une référence directe à l'état interne ;
     * pour éviter des modifications accidentelles, envisagez de retourner une copie.
     * Exemple de copie : {@code return Arrays.stream(board).map(int[]::clone).toArray(int[][]::new);}
     *
     * @return Un tableau 2D d'entiers représentant le plateau de jeu.
     */
    public int[][] getBoard() { return board; }

    /**
     * Récupère le score du joueur 1.
     *
     * @return Le score du joueur 1.
     */
    public int getPlayer1Score() { return player1Score; }

    /**
     * Récupère le score du joueur 2.
     *
     * @return Le score du joueur 2.
     */
    public int getPlayer2Score() { return player2Score; }

    /**
     * Récupère l'identifiant du joueur dont c'est le tour.
     *
     * @return L'identifiant du joueur courant.
     */
    public String getCurrentPlayerId() { return currentPlayerId; }

    /**
     * Vérifie si la partie est terminée.
     *
     * @return true si la partie est terminée, false sinon.
     */
    public boolean isGameOver() { return isGameOver; }

    /**
     * Récupère l'identifiant du joueur gagnant.
     *
     * @return L'identifiant du gagnant, ou null si la partie n'est pas terminée ou s'il n'y a pas de gagnant unique.
     */
    public String getWinnerId() { return winnerId; }

    /**
     * Récupère le statut actuel de la partie.
     *
     * @return Le statut de la partie (ex: "playing", "finished").
     */
    public String getStatus() { return status; }

    /**
     * Récupère l'identifiant du joueur 1.
     *
     * @return L'identifiant du joueur 1.
     */
    public String getPlayer1Id() { return player1Id; }

    /**
     * Récupère l'identifiant du joueur 2.
     *
     * @return L'identifiant du joueur 2.
     */
    public String getPlayer2Id() { return player2Id; }

    /**
     * Récupère le score cible à atteindre pour gagner.
     *
     * @return Le score cible (par exemple, 2048).
     */
    public int getTargetScore() { return targetScore; }


    /**
     * Calcule et retourne le score de l'adversaire par rapport à l'identifiant du joueur fourni.
     *
     * @param myActualPlayerId L'identifiant du joueur pour lequel on veut connaître le score de l'adversaire.
     * @return Le score de l'adversaire si {@code myActualPlayerId} correspond à l'un des joueurs, sinon 0. Retourne 0 si {@code myActualPlayerId} est null.
     */
    public int getOpponentScore(String myActualPlayerId) {
        if (myActualPlayerId == null) {
            return 0;
        }
        if (myActualPlayerId.equals(player1Id)) {
            return player2Score;
        } else if (myActualPlayerId.equals(player2Id)) {
            return player1Score;
        }
        return 0;
    }

    /**
     * Calcule et retourne le score du joueur correspondant à l'identifiant fourni.
     *
     * @param myActualPlayerId L'identifiant du joueur dont on veut connaître le score.
     * @return Le score du joueur si {@code myActualPlayerId} correspond à l'un des joueurs, sinon 0. Retourne 0 si {@code myActualPlayerId} est null.
     */
    public int getMyScore(String myActualPlayerId) {
        if (myActualPlayerId == null) {
            return 0;
        }
        if (myActualPlayerId.equals(player1Id)) {
            return player1Score;
        } else if (myActualPlayerId.equals(player2Id)) {
            return player2Score;
        }
        return 0;
    }
}