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

import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.score.LastWinsScore;
import eu.mhsl.minenet.minigames.util.Position;
import io.github.togar2.pvp.feature.CombatFeatures;
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.item.ItemDropEvent;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

class Pillars extends StatelessGame {
    private int spawnPosx = 0;
    private int spawnPosz = 0;
    private final int pillarSpacing = 10;
    private final int pillarRowCount = 5;

    public Pillars() {
        super(Dimension.THE_END.key, "Pillars", new LastWinsScore());
        this.getScore().setIgnoreLastPlayers(1);

        this.eventNode().addChild(
            CombatFeatures.empty()
                .add(CombatFeatures.VANILLA_ATTACK)
                .add(CombatFeatures.VANILLA_DAMAGE)
                .add(CombatFeatures.VANILLA_KNOCKBACK)
                .build().createNode()
        );
    }

    @Override
    protected boolean onPlayerJoin(Player p) {
        Pos pos = new Pos(this.spawnPosx * this.pillarSpacing, 100, this.spawnPosz * this.pillarSpacing);
        this.setBlock(pos.sub(0, 1, 0), Block.BEDROCK);

        if(this.spawnPosx >= this.pillarRowCount) {
            this.spawnPosx = 0;
            this.spawnPosz++;
        }
        this.spawnPosx++;
        MinecraftServer.getSchedulerManager().scheduleNextTick(() -> p.teleport(pos.add(0.5, 0, 0.5)));

        return super.onPlayerJoin(p);
    }

    @Override
    protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) {}

    @Override
    protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) {}

    @Override
    protected void onItemDrop(@NotNull ItemDropEvent itemDropEvent) {}

    @Override
    public Pos getSpawn() {
        return new Pos(0, 105, 0);
    }

    @Override
    protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
        var player = playerMoveEvent.getPlayer();

        if(this.isBeforeBeginning && Position.hasPositionChanged(player.getPosition(), playerMoveEvent.getNewPosition()))
            playerMoveEvent.setCancelled(true);

        if(playerMoveEvent.getNewPosition().y() < 80) {
            this.getScore().insertResult(player);
            player.teleport(this.getSpawn());
            player.setGameMode(GameMode.SPECTATOR);
        }
    }

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

        MinecraftServer.getSchedulerManager().submitTask(() -> {
            List<Material> materials = Material.values().stream()
                .filter(material -> !material.equals(Material.AIR))
                .toList();
            this.getPlayers().forEach(player -> {
                ItemStack item = ItemStack.of(materials.get(ThreadLocalRandom.current().nextInt(Material.values().toArray().length)));
                player.getInventory().addItemStack(item);
            });

            return TaskSchedule.seconds(5);
        });
    }
}
