/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.lobby.particle;

import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import de.steamwar.lobby.LobbySystem;
import de.steamwar.lobby.particle.particles.*;
import de.steamwar.lobby.particle.particles.custom.CustomEasterParticle;
import de.steamwar.lobby.particle.particles.custom.CustomPlayerParticle;
import de.steamwar.lobby.particle.particles.custom.CustomTeamParticle;
import de.steamwar.lobby.special.easter.EggHunt;
import de.steamwar.lobby.util.LobbyPlayer;
import de.steamwar.sql.*;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@UtilityClass
public class ParticleInventory {

    private final Class<?>[] PARTICLES = {
            PlayerParticle.class,
            CustomPlayerParticle.class,
            TeamParticle.class,
            CustomTeamParticle.class,
            RainCloudParticle.class,
            ServerTeamParticle.class,
            EventParticle.class,
            EventParticlePlacement.class,
            EventParticleParticipation.class,
            EasterParticle.class,
            CustomEasterParticle.class,
    };

    public String convertToString(ParticleEnum particleEnum) {
        return particleEnum.getClass().getSimpleName() + "@" + ((Enum<?>)particleEnum).name();
    }

    public ParticleEnum convertFromString(String string) {
        String[] split = string.split("@");
        Class<?> clazz = null;
        for (Class<?> aClass : PARTICLES) {
            if (aClass.getSimpleName().equals(split[0])) {
                clazz = aClass;
                break;
            }
        }
        if (clazz != null) {
            try {
                return (ParticleEnum) Enum.valueOf((Class<? extends Enum>) clazz, split[1]);
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    public void openInventory(Player player, boolean onlyUnlocked) {
        LobbyPlayer lobbyPlayer = LobbyPlayer.getLobbyPlayer(player.getUniqueId());

        SteamwarUser user = SteamwarUser.get(player.getUniqueId());
        Set<Integer> events = user.getTeam() == 0 ? new HashSet<>() : TeamTeilnahme.getEvents(user.getTeam()).stream().map(Event::getEventID).collect(Collectors.toSet());
        String eggHuntConfig = UserConfig.getConfig(user.getId(), EggHunt.EGG_HUNT_CONFIG_KEY);

        AtomicBoolean hasOneLocked = new AtomicBoolean(false);
        List<SWListInv.SWListEntry<ParticleEnum>> particleList = new ArrayList<>();
        for (Class<?> clazz : PARTICLES) {
            addParticles(particleList, (ParticleEnum[]) clazz.getEnumConstants(), player, onlyUnlocked, hasOneLocked, user, events, eggHuntConfig);
        }
        for (int i = 0; i < particleList.size() % 45; i++) {
            particleList.add(new SWListInv.SWListEntry<>(new SWItem(Material.BLACK_STAINED_GLASS_PANE, " "), null));
        }

        SWListInv<ParticleEnum> particleSWListInv = new SWListInv<>(player, LobbySystem.getMessage().parse("PARTICLE_INVENTORY", player), false, particleList, (clickType, particle) -> {
            if (particle == null) return;
            lobbyPlayer.setParticle(particle);
            player.closeInventory();
            if (ParticleListener.disabled(player)) {
                LobbySystem.getMessage().send("PARTICLE_DEACTIVATED", player);
            }
        });
        particleSWListInv.setItem(48, Material.BARRIER, LobbySystem.getMessage().parse("PARTICLE_DESELECT", player), new ArrayList<>(), false, clickType -> {
            lobbyPlayer.setParticle(null);
        });
        if (!hasOneLocked.get()) {
            particleSWListInv.setItem(50, Material.GRAY_BANNER, LobbySystem.getMessage().parse("PARTICLE_SHOW_HAS_ALL", player), new ArrayList<>(), false, clickType -> {
            });
        } else if (onlyUnlocked) {
            particleSWListInv.setItem(50, Material.LIME_BANNER, LobbySystem.getMessage().parse("PARTICLE_SHOW_ALL", player), new ArrayList<>(), false, clickType -> {
                openInventory(player, false);
            });
        } else {
            particleSWListInv.setItem(50, Material.RED_BANNER, LobbySystem.getMessage().parse("PARTICLE_SHOW_UNLOCKED", player), new ArrayList<>(), false, clickType -> {
                openInventory(player, true);
            });
        }
        particleSWListInv.open();
    }

    private void addParticles(List<SWListInv.SWListEntry<ParticleEnum>> particleList, ParticleEnum[] particleEnums, Player player, boolean onlyUnlocked, AtomicBoolean hasOneLocked, SteamwarUser user, Set<Integer> events, String eggHuntConfig) {
        for (ParticleEnum particle : particleEnums) {
            ParticleData particleData = particle.getParticle();
            SWItem swItem = particleData.toSWItem(player, user, events, eggHuntConfig);
            if (particleData.getRequirement().test(user, events, eggHuntConfig)) {
                particleList.add(new SWListInv.SWListEntry<>(swItem, particle));
            } else {
                hasOneLocked.set(true);
                if (!onlyUnlocked) {
                    particleList.add(new SWListInv.SWListEntry<>(swItem, null));
                }
            }
        }
        for (int i = 0; i < particleList.size() % 9; i++) {
            particleList.add(new SWListInv.SWListEntry<>(new SWItem(Material.BLACK_STAINED_GLASS_PANE, " "), null));
        }
    }
}
