package eu.mhsl.minenet.minigames.instance.game.stateless.config;

import eu.mhsl.minenet.minigames.instance.game.Game;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory;
import eu.mhsl.minenet.minigames.util.InventoryItemAlignment;
import eu.mhsl.minenet.minigames.instance.room.Room;
import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventListener;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.inventory.click.ClickType;
import net.minestom.server.inventory.condition.InventoryConditionResult;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.sound.SoundEvent;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class GameConfigurationInventory extends InteractableInventory {
    private final Map<Integer, Option<?>> map = new HashMap<>();

    final private Room room;
    final private GameFactory factory;
    final private Player p;

    public GameConfigurationInventory(Room room, Player p, GameFactory factory) {
        super(InventoryType.CHEST_5_ROW, factory.name().getAssembled(p));
        this.room = room;
        this.p = p;
        this.factory = factory;

        room.eventNode()
                .addListener(AddEntityToInstanceEvent.class, addEntityToInstanceEvent -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton))
                .addListener(RemoveEntityFromInstanceEvent.class, removeEntityFromInstanceEvent -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton));

        ConfigManager config = factory.configuration();

        setClickableItem(
                ItemStack.builder(Material.RED_WOOL)
                        .customName(
                                TranslatedComponent.byId("common#back")
                                        .setColor(NamedTextColor.RED)
                                        .getAssembled(p)
                        )
                        .build(),
                0,
                itemClick -> itemClick.getPlayer().closeInventory(),
                true
        );

        setDummyItem(Material.BLACK_STAINED_GLASS_PANE,1);

        setDummyItem(
                ItemStack.builder(Material.NAME_TAG)
                        .customName(
                                factory.name().setColor(NamedTextColor.GOLD).getAssembled(p)
                        )
                        .build(),
                4
        );

        setDummyItem(Material.BLACK_STAINED_GLASS_PANE,7);

        updatePlayButton();

        for(int i = 9; i <= 17; i++) {
            setDummyItem(Material.BLACK_STAINED_GLASS_PANE, i);
        }

        if(config == null) {
            setDummyItem(
                    ItemStack.builder(Material.BARRIER)
                            .customName(
                                    TranslatedComponent.byId("room#noOption").setColor(NamedTextColor.RED).getAssembled(p)
                            )
                            .lore(
                                    TranslatedComponent.assemble("room#noOptionDescription", p)
                            )
                            .build(),
                    31
            );

        } else {
            int offset = 18;
            InventoryItemAlignment itemAlignment = new InventoryItemAlignment(config.getAll().size(), 3);
            for(Option<?> item : config.getAll()) {
                InventoryItemAlignment.ItemOffset current = itemAlignment.next();
                map.put(offset + current.get(), item);

                setDummyItem(
                        item.getCurrent(p),
                        offset + current.get()
                );
            }
        }

    }

    @Override
    protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) {
        inventoryConditionResult.setCancel(true);

        if(!map.containsKey(slot)) return;

        Option<?> item = map.get(slot);
        setDummyItem(
                item.getNext(p),
                slot
        );

        update();

    }

    private void updatePlayButton() {
        RestrictionHandler restrictionHandler = factory.globalRestrictions();
        RestrictionData restrictionData = new RestrictionData(room);

        if(restrictionHandler.canPlay(restrictionData)) {

            setClickableItem(
                    ItemStack.builder(restrictionHandler.getWarnings(restrictionData).size() > 0 ? Material.YELLOW_WOOL : Material.GREEN_WOOL)
                            .customName(TranslatedComponent.byId("restriction#success").setColor(NamedTextColor.GREEN).getAssembled(p))
                            .lore(restrictionHandler.getWarnings(restrictionData).stream().map(translatedComponent -> translatedComponent.getAssembled(p)).collect(Collectors.toList()))
                            .build(),
                    8,
                    itemClick -> Game.initialize(factory, map.values().stream().toList(), itemClick.getPlayer()),
                    true
            );

        } else {

            setClickableItem(
                    ItemStack.builder(Material.RED_WOOL)
                            .customName(TranslatedComponent.byId("restriction#fail").setColor(NamedTextColor.RED).getAssembled(p))
                            .lore(
                                    restrictionHandler.getRestrictions()
                                            .stream()
                                            .filter(iRestriction -> iRestriction.calculate(restrictionData).type().equals(Restriction.Type.FAIL))
                                            .map(iRestriction -> iRestriction.calculate(restrictionData).description().getAssembled(p))
                                            .collect(Collectors.toList()))
                            .build(),
                    8,
                    itemClick -> {
                        if(restrictionHandler.canPlay(restrictionData)) {
                            updatePlayButton();
                            return;
                        }
                        itemClick.getPlayer().playSound(Sound.sound(SoundEvent.ENTITY_SILVERFISH_DEATH, Sound.Source.AMBIENT, 1f, 1f));
                    },
                    false
            );

        }

        update();
    }
}
