package eu.mhsl.minenet.minigames.score.tournament;

import eu.mhsl.minenet.minigames.Resource;
import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.MineNetInstance;
import eu.mhsl.minenet.minigames.instance.Spawnable;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.anvil.AnvilLoader;

import java.util.Comparator;
import java.util.List;
import java.util.Set;

public class TournamentDisplay extends MineNetInstance implements Spawnable {
    private final List<Set<Player>> places;
    private final Tournament tournament;

    private final Pos[] placePositions = new Pos[]{
        new Pos(8.5, -56, 22.5, 180, 0),
        new Pos(12.5, -57, 20.5, 180, 0),
        new Pos(4.5, -58, 20.5, 180, 0)
    };

    public TournamentDisplay(Tournament tournament) {
        super(Dimension.OVERWORLD.key);
        this.setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath()));
        this.places = tournament.getPlaces();
        this.tournament = tournament;

        this.places.forEach(players -> players.forEach(player -> player.setGameMode(GameMode.ADVENTURE)));

        this.eventNode().addListener(PlayerMoveEvent.class, playerMoveEvent -> {
            if(this.isOnDisplay(playerMoveEvent.getPlayer()) && !playerMoveEvent.getNewPosition().sameBlock(this.placePositions[this.getRankPosition(playerMoveEvent.getPlayer())])) {
                playerMoveEvent.setCancelled(true);
            }
        });
    }

    private boolean isOnDisplay(Player player) {
        if(this.getRankPosition(player) == -1) return false;
        return this.getRankPosition(player) < this.placePositions.length;
    }

    private int getRankPosition(Player player) {
        for(int i = 0; i < this.places.size(); i++) {
            if(this.places.get(i).contains(player)) return i;
        }
        return -1;
    }

    @Override
    protected boolean onPlayerJoin(Player p) {
        MinecraftServer.getSchedulerManager().scheduleNextTick(() -> {
            if(this.isOnDisplay(p)) {
                p.sendMessage("You are on Display!");
                p.teleport(this.placePositions[this.getRankPosition(p)]);
            }
        });
        List<Player> players = this.places.stream()
            .flatMap(s -> s.stream().sorted(Comparator.comparing(Player::getUsername)))
            .toList();
        new ChatMessage(Icon.STAR)
            .list(players.stream().map(player -> String.format("%d. %s - %s Punkte", this.getRankPosition(player) + 1, player.getUsername(), this.tournament.getGameScores().get(player))).toList())
            .send(p);
        return false;
    }

    @Override
    public Pos getSpawn() {
        return new Pos(8.5, -59, 11.5);
    }
}
