/*
 *   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.linkage.Linked;
import de.steamwar.lobby.LobbySystem;
import de.steamwar.lobby.jumpandrun.JumpAndRun;
import de.steamwar.lobby.listener.PlayerSpawn;
import de.steamwar.lobby.util.LobbyPlayer;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import org.bukkit.Bukkit;
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.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;

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

@Linked
public class ParticleListener implements Listener {

    private static final int PLAYER_MAX_SIZE = 20;
    private static final int SERVER_TEAM_MAX_SIZE = 40;

    private static double deg = 0;

    private static Map<Player, Integer> movingPlayers = new HashMap<>();

    public ParticleListener() {
        Bukkit.getScheduler().runTaskTimer(LobbySystem.getInstance(), () -> {
            movingPlayers.replaceAll((player, integer) -> integer - 1);
            movingPlayers.entrySet().removeIf(entry -> entry.getValue() <= 0);
            deg += 0.1;
            if (deg > 360) deg = 0;
            Bukkit.getOnlinePlayers().forEach(player -> {
                if (disabled(player)) return;
                if (JumpAndRun.isPlayerInJumpAndRun(player)) return;
                LobbyPlayer lobbyPlayer = LobbyPlayer.getLobbyPlayer(player.getUniqueId());
                ParticleEnum particle = lobbyPlayer.getParticle();
                if (particle == null) return;
                ParticleData particleData = particle.getParticle();
                ParticleElement particleElement = particleData.getParticleElement();
                if (particleElement.tickType() == ParticleTickType.ALWAYS) {
                    particleElement.tick(new ParticleTickData(player.getWorld(), player, deg, movingPlayers.containsKey(player)));
                }
            });
        }, 0, 1);
    }

    @EventHandler(priority = EventPriority.NORMAL)
    public void handlePlayerInteract(PlayerInteractEvent event) {
        Player player = event.getPlayer();
        if (JumpAndRun.isPlayerInJumpAndRun(player)) return;
        if (!PlayerSpawn.PARTICLE.equals(event.getItem())) return;
        event.setCancelled(true);

        ParticleInventory.openInventory(player, true);
    }

    @EventHandler
    public void handlePlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        if (disabled(player)) return;
        if (JumpAndRun.isPlayerInJumpAndRun(player)) return;
        LobbyPlayer lobbyPlayer = LobbyPlayer.getLobbyPlayer(player.getUniqueId());
        ParticleEnum particle = lobbyPlayer.getParticle();
        if (particle == null) return;

        ParticleData particleData = particle.getParticle();
        ParticleElement particleElement = particleData.getParticleElement();
        if (particleElement.tickType() == ParticleTickType.MOVE) {
            particleElement.tick(new ParticleTickData(player.getWorld(), player, deg, true));
        }
        if (event.getFrom().getX() != event.getTo().getX() || event.getFrom().getY() != event.getTo().getY() || event.getFrom().getZ() != event.getTo().getZ()) {
            movingPlayers.put(player, 5);
        }
    }

    @EventHandler(ignoreCancelled = true)
    public void onPlayerQuit(PlayerQuitEvent event) {
        movingPlayers.remove(event.getPlayer());
    }

    @EventHandler
    public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
        if (PlayerSpawn.PARTICLE.equals(event.getPlayer().getInventory().getItemInMainHand())) {
            event.setCancelled(true);
        }
    }

    public static boolean disabled(Player player) {
        SteamwarUser user = SteamwarUser.get(player.getUniqueId());
        if (Bukkit.getOnlinePlayers().size() > SERVER_TEAM_MAX_SIZE) return true;
        return Bukkit.getOnlinePlayers().size() > PLAYER_MAX_SIZE && !user.hasPerm(UserPerm.TEAM);
    }
}
