/*
 *   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.fightsystem.utils;

import de.steamwar.Reflection;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.listener.Recording;
import de.steamwar.fightsystem.record.GlobalRecorder;
import net.minecraft.world.InteractionHand;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerPickupArrowEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import org.bukkit.scoreboard.Team;

import java.util.HashMap;
import java.util.Map;

public class BountifulWrapper {
    public static final BountifulWrapper impl = new BountifulWrapper();

    private static final Class<?> enumHand = InteractionHand.class;
    private static final Object mainHand = enumHand.getEnumConstants()[0];
    private static final Reflection.Field<?> blockPlaceHand = Reflection.getField(Recording.blockPlacePacket, enumHand, 0);

    public boolean mainHand(Object packet) {
        return blockPlaceHand.get(packet) == mainHand;
    }

    public boolean bowInHand(boolean mainHand, Player p) {
        return (mainHand ? p.getInventory().getItemInMainHand() : p.getInventory().getItemInOffHand()).getType() == Material.BOW;
    }

    public void setAttackSpeed(Player player) {
        AttributeInstance attribute = player.getAttribute(Attribute.ATTACK_SPEED);
        attribute.setBaseValue(16);
    }

    public void setNametagVisibility(Team team) {
        team.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.FOR_OWN_TEAM);
    }

    public Listener newDenyArrowPickupListener() {
        return new Listener() {
            @EventHandler
            public void onArrowPickup(PlayerPickupArrowEvent e) {
                if (Fight.fighting(e.getPlayer())) e.setCancelled(true);
            }
        };
    }

    public Listener newDenyHandSwapListener() {
        return new Listener() {
            @EventHandler
            public void onSwapItems(PlayerSwapHandItemsEvent event) {
                if (Fight.fighting(event.getPlayer())) event.setCancelled(true);
            }
        };
    }

    public void recordHandItems(Player player) {
        GlobalRecorder.getInstance().item(player, Recording.disarmNull(player.getInventory().getItemInMainHand()), "MAINHAND");
        GlobalRecorder.getInstance().item(player, Recording.disarmNull(player.getInventory().getItemInOffHand()), "OFFHAND");
    }

    public Listener newHandSwapRecorder() {
        return new Listener() {
            @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
            public void onItemSwap(PlayerSwapHandItemsEvent e) {
                if (Recording.isNotSent(e.getPlayer()))
                    return;

                Player player = e.getPlayer();
                GlobalRecorder.getInstance().item(player, Recording.disarmNull(e.getMainHandItem()), "MAINHAND");
                GlobalRecorder.getInstance().item(player, Recording.disarmNull(e.getOffHandItem()), "OFFHAND");
            }
        };
    }

    public void spawnParticle(World world, String particleName, double x, double y, double z) {
        world.spawnParticle(Particle.valueOf(particleName), x, y, z, 1);
    }

    private final Map<Player, BossBar> barMap = new HashMap<>();

    public void sendBar(Player player, FightTeam team, double progress, String text) {
        barMap.keySet().removeIf(p -> !p.isOnline());

        if (!barMap.containsKey(player)) {
            BossBar bar = Bukkit.createBossBar(player.getName(), BarColor.WHITE, BarStyle.SOLID);
            barMap.put(player, bar);
            bar.addPlayer(player);
        }

        BossBar bar = barMap.get(player);
        BarColor color = chat2bar(team.getColor());
        if (bar.getColor() != color) bar.setColor(color);

        if (bar.getProgress() != progress) bar.setProgress(progress);

        if (!bar.getTitle().equals(text)) bar.setTitle(text);
    }

    private BarColor chat2bar(ChatColor color) {
        switch (color) {
            case DARK_BLUE:
            case DARK_AQUA:
            case BLUE:
            case AQUA:
                return BarColor.BLUE;
            case GREEN:
            case DARK_GREEN:
                return BarColor.GREEN;
            case DARK_RED:
            case RED:
                return BarColor.RED;
            case DARK_PURPLE:
                return BarColor.PURPLE;
            case GOLD:
            case YELLOW:
                return BarColor.YELLOW;
            case LIGHT_PURPLE:
                return BarColor.PINK;
            case BLACK:
            case WHITE:
            case GRAY:
            case DARK_GRAY:
            default:
                return BarColor.WHITE;
        }
    }
}
