package eu.jonahbauer.wizard.core.states.round;

import eu.jonahbauer.wizard.core.states.GameData;
import eu.jonahbauer.wizard.core.Game;
import eu.jonahbauer.wizard.core.states.GameState;
import eu.jonahbauer.wizard.core.states.game.Finishing;
import eu.jonahbauer.wizard.common.messages.observer.ScoreMessage;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import static eu.jonahbauer.wizard.core.states.GameData.*;

public final class FinishingRound extends RoundState {

    public FinishingRound(GameData data) {
        super(data.requireEach(PLAYERS, PREDICTIONS).require(TRICKS, SCORE));
    }

    @Override
    public Optional<GameState> onEnter(Game game) {
        var points = getPoints();
        game.notify(new ScoreMessage(points));

        var score = new HashMap<>(get(SCORE));
        points.forEach((uuid, amount) -> score.merge(uuid, amount, Integer::sum));

        GameData data = getData().with(SCORE, Map.copyOf(score));

        if (60 / getPlayerCount() == get(ROUND) + 1) {
            return transition(new Finishing(data));
        } else {
            return transition(new StartingRound(data.with(ROUND, get(ROUND) + 1)));
        }
    }

    private Map<UUID, Integer> getPoints() {
        var points = new HashMap<UUID, Integer>();
        for (UUID player : get(PLAYERS)) {
            int prediction = get(PREDICTIONS).get(player);
            int tricks = get(TRICKS).getOrDefault(player, 0);

            if (tricks == prediction) {
                points.put(player, 20 + 10 * tricks);
            } else {
                points.put(player, -10 * Math.abs(tricks - prediction));
            }
        }
        return points;
    }
}
