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

import eu.mhsl.minenet.minigames.Resource;
import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars.data.BedwarsTeam;
import eu.mhsl.minenet.minigames.message.type.ActionBarMessage;
import eu.mhsl.minenet.minigames.score.LastWinsScore;
import eu.mhsl.minenet.minigames.util.MaterialUtil;
import eu.mhsl.minenet.minigames.util.Position;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.ItemEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.PickupItemEvent;
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.anvil.AnvilLoader;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.timer.ExecutionType;
import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.*;

public class Bedwars extends StatelessGame {

    List<Point> placedBlocks = new ArrayList<>();
    List<BedwarsTeam> teams = new ArrayList<>();


    public Bedwars() throws IOException {
        super(Dimension.OVERWORLD.key, "Bedwars", new LastWinsScore());
        setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test")));

        Configuration config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(Resource.GAME_MAP.getPath().resolve("bedwars/test/config.yml").toFile());
        List<String> teamNames = config.getStringList("setup.teams");
        teamNames.forEach(teamName -> {
            String path = "teams." + teamName;
            teams.add(new BedwarsTeam(
                    config.getString(path + ".name"),
                    Position.getPosFromCommaSeparated(config.getString(path + ".pos.spawn")),
                    Position.getPosFromCommaSeparated(config.getString(path + ".pos.spawner")),
                    config.getStringList(path + ".pos.bed").stream().map(Position::getPosFromCommaSeparated).toList().toArray(new Pos[0]),
                    MaterialUtil.fromString(config.getString(path + ".material.block"), Material.BLACK_WOOL)
            ));
        });

        eventNode().addListener(PickupItemEvent.class, pickupItemEvent -> {
            if(pickupItemEvent.getEntity() instanceof Player p) {
                p.getInventory().addItemStack(pickupItemEvent.getItemStack());
            }
        });
    }

    @Override
    protected void onItemDrop(@NotNull ItemDropEvent itemDropEvent) {
        itemDropEvent.setCancelled(false);
    }

    @Override
    protected void onStart() {
        scheduler().submitTask(() -> {
            if(!isRunning) return TaskSchedule.stop();

            teams.forEach(bedwarsTeam -> {
                ItemEntity item = new ItemEntity(ItemStack.of(bedwarsTeam.getBlock()));
                item.setNoGravity(true);
                item.setInstance(this, bedwarsTeam.getSpawner());
            });

            return TaskSchedule.stop();
        }, ExecutionType.TICK_END);

    }

    @Override
    protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) {
        placedBlocks.add(playerBlockPlaceEvent.getBlockPosition());
    }

    @Override
    protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) {
        if(!placedBlocks.contains(playerBlockBreakEvent.getBlockPosition())) playerBlockBreakEvent.setCancelled(true);

        teams.forEach(bedwarsTeam -> {
            if(Arrays.stream(bedwarsTeam.getBed()).anyMatch(pos -> pos.sameBlock(playerBlockBreakEvent.getBlockPosition())))
                breakBed(bedwarsTeam);
        });

        if(playerBlockBreakEvent.isCancelled())
            new ActionBarMessage().appendStatic(Component.text("BLAH")).send(playerBlockBreakEvent.getPlayer());
    }

    @Override
    protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
        if(playerMoveEvent.getNewPosition().y() < 0) death(playerMoveEvent.getPlayer());
    }

    private void breakBed(BedwarsTeam team) {
        team.removeBed();
        for (Pos blockPos : team.getBed()) {
            setBlock(blockPos, Material.AIR.block());
        }
    }

    private void death(Player p) {

    }

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