package fr.monkhanny.dorfromantik.game;

import fr.monkhanny.dorfromantik.enums.Biome;
import fr.monkhanny.dorfromantik.enums.TileOrientation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Manages the score of the game, keeping track of biome pockets.
 */
public class ScoreManager {
    private List<Pocket> pockets;
    private int currentScore;

    public ScoreManager() {
        pockets = new ArrayList<>();
        currentScore = 0;
    }

    /**
     * Adds a tile to the appropriate pocket or creates a new one if necessary.
     *
     * @param tile The tile to add.
     */
    public void addTile(Tile tile) {
        Map<Biome, Pocket> biomeToPocketMap = new HashMap<>();
    
        // Trouver les poches existantes auxquelles cette tuile peut être connectée, en vérifiant les voisins directs
        for (TileOrientation orientation : TileOrientation.values()) {
            Biome biome = tile.getBiome(orientation);
            if (biome != null) {
                // Trouver la tuile voisine dans la direction donnée
                Tile neighborTile = tile.getNeighbor(orientation);
                if (neighborTile != null && neighborTile.getBiome(orientation.oppositeOrientation()) == biome) {
                    Pocket connectedPocket = findPocketForTile(neighborTile, biome);
                    if (connectedPocket != null && !biomeToPocketMap.containsKey(biome)) {
                        biomeToPocketMap.put(biome, connectedPocket);
                    }
                }
            }
        }
    
        // Ajouter la tuile aux poches existantes ou créer une nouvelle poche si aucune n'est trouvée
        for (TileOrientation orientation : TileOrientation.values()) {
            Biome biome = tile.getBiome(orientation);
            if (biome != null) {
                if (biomeToPocketMap.containsKey(biome)) {
                    // Ajouter la tuile à la poche existante pour ce biome
                    biomeToPocketMap.get(biome).addTile(tile);
                } else {
                    // Créer une nouvelle poche pour ce biome
                    Pocket newPocket = new Pocket(biome);
                    newPocket.addTile(tile);
                    pockets.add(newPocket);
                    biomeToPocketMap.put(biome, newPocket);
                }
            }
        }
    
        // Recalculer le score après avoir ajouté la tuile
        recalculateScore();
    }
    
    /**
     * Finds the pocket associated with the given tile and biome.
     *
     * @param tile  The tile to check.
     * @param biome The biome to match.
     * @return The connected pocket, or null if none found.
     */
    private Pocket findPocketForTile(Tile tile, Biome biome) {
        for (Pocket pocket : pockets) {
            if (pocket.getBiome() == biome && pocket.getTiles().contains(tile)) {
                return pocket;
            }
        }
        return null;
    }

    /**
     * Recalculates the score based on the current pockets.
     */
    private void recalculateScore() {
        currentScore = 0;
        for (Pocket pocket : pockets) {
            currentScore += Math.pow(pocket.getSize(), 2);
        }
    }

    public int getCurrentScore() {
        return currentScore;
    }
}