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

import eu.jonahbauer.wizard.core.machine.Game;
import eu.jonahbauer.wizard.common.messages.player.PlayerMessage;
import lombok.Getter;
import org.jetbrains.annotations.Unmodifiable;

import java.util.UUID;

import static eu.jonahbauer.wizard.core.machine.states.GameData.CURRENT_PLAYER;
import static eu.jonahbauer.wizard.core.machine.states.GameData.PLAYERS;

@Unmodifiable
public abstract class GameState implements State<GameState, Game> {
    @Getter
    private final GameData data;

    public GameState(GameData data) {
        this.data = data.require(PLAYERS).clean();
    }

    protected final void transition(Game game, GameState state) {
        game.transition(this, state);
    }

    protected final void timeout(Game game) {
        game.timeout(this, getTimeout(game, false));
    }

    protected final long getTimeout(Game game, boolean absolute) {
        return (absolute ? System.currentTimeMillis() : 0) + game.getConfig().timeout();
    }

    public void onMessage(Game game, UUID player, PlayerMessage message) {
        throw new IllegalStateException("You cannot do that right now.");
    }

    @Override
    public String toString() {
        return getClass().getSimpleName();
    }

    public <T> T get(GameData.Key<T> key) {
        return getData().get(key);
    }

    public int getPlayerCount() {
        return get(PLAYERS).size();
    }

    public UUID getPlayer(int index) {
        return get(PLAYERS).get(index);
    }

    public UUID getNextPlayer() {
        return getNextPlayer(get(CURRENT_PLAYER));
    }

    public UUID getNextPlayer(UUID player) {
        var players = get(PLAYERS);
        var index = players.indexOf(player);
        if (index == -1) {
            throw new AssertionError("Player is not a valid player.");
        } else if (index == players.size() - 1) {
            return players.get(0);
        } else {
            return players.get(index + 1);
        }

    }
}
