package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace;

import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.score.FirstWinsScore;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class BlockBreakRace extends StatelessGame {
    private final int height;
    private int spawnCount = 0;

    public BlockBreakRace(int height) {
        super(Dimension.OVERWORLD.key, "blockBreakRace", new FirstWinsScore());
        this.height = height;
        this.setGenerator(new BlockBreakRaceGenerator(height));
    }

    @Override
    protected boolean onPlayerJoin(Player p) {
        PlayerInventory inv = p.getInventory();
        inv.addItemStack(ItemStack.of(Material.DIAMOND_PICKAXE));
        inv.addItemStack(ItemStack.of(Material.DIAMOND_AXE));
        inv.addItemStack(ItemStack.of(Material.DIAMOND_SHOVEL));
        return super.onPlayerJoin(p);
    }

    @Override
    protected void onStart() {
        this.getPlayers().forEach(player -> player.setGameMode(GameMode.SURVIVAL));
    }

    @Override
    protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
        List<Material> allowedMaterials = List.of(Material.STONE, Material.OAK_PLANKS, Material.DIRT);
        if(!allowedMaterials.contains(event.getBlock().registry().material())) event.setCancelled(true);
        if(this.isBeforeBeginning) event.setCancelled(true);
    }

    @Override
    protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
        if(this.isBeforeBeginning) return;
        if(playerMoveEvent.getNewPosition().y() < BlockBreakRaceGenerator.BOTTOM_Y) {
            Player player = playerMoveEvent.getPlayer();
            this.getScore().insertResult(player);
            player.setGameMode(GameMode.SPECTATOR);
            player.getInventory().clear();
        }
    }

    @Override
    public Pos getSpawn() {
        int idx = this.spawnCount++;

        int cols = BlockBreakRaceGenerator.ROW_OFFSETS_X.length;
        int rows = BlockBreakRaceGenerator.ROW_OFFSETS_Z.length;
        int perChunk = cols * rows;
        int zChunk = idx / perChunk;

        int gridIndex = idx % perChunk;
        int xIndex = gridIndex % cols;
        int zIndex = gridIndex / cols;

        int localX = BlockBreakRaceGenerator.ROW_OFFSETS_X[xIndex];
        int localZ = BlockBreakRaceGenerator.ROW_OFFSETS_Z[zIndex];

        int absZ = (zChunk * 16) + localZ;
        return new Pos(localX, BlockBreakRaceGenerator.BOTTOM_Y + this.height + 1, absZ).add(0.5);
    }
}
