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

import de.steamwar.bausystem.commands.*;
import de.steamwar.bausystem.world.*;
import de.steamwar.bausystem.world.regions.Region;
import de.steamwar.core.Core;
import de.steamwar.providers.BauServerInfo;
import de.steamwar.scoreboard.SWScoreboard;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;

import java.util.UUID;
import java.util.logging.Level;

public class BauSystem extends JavaPlugin implements Listener {

    private static BauSystem plugin;
    private static Integer owner;
    public static final String PREFIX = "§eBauSystem§8» §7";

    private BukkitTask autoShutdown;

    @Override
    public void onEnable() {
        Core.setServerName("Dev");
        plugin = this;

        Mapper.init();

        new CommandTrace();
        new CommandTPSLimiter();
        new CommandNV();
        new CommandReset();
        new CommandSpeed();
        new CommandTNT();
        new CommandGamemode();
        new CommandClear();
        new CommandTime();
        new CommandTeleport();
        new CommandFire();
        new CommandFreeze();
        new CommandTestblock();
        new CommandInfo();
        new CommandProtect();
        new CommandSkull();
        new CommandLoader();
        new CommandLockschem();
        new CommandDebugStick();
        new CommandGills();
        new CommandDetonator();
        new CommandScript();
        new CommandScriptVars();
        new CommandRedstoneTester();
        new CommandGUI();
        new CommandWorldSpawn();
        new CommandRegion();
        new CommandSelect();
        new CommandKillAll();

        if (Core.getVersion() > 14 && Region.buildAreaEnabled()) {
            new CommandColor();
        }

        Bukkit.getPluginManager().registerEvents(this, this);
        Bukkit.getPluginManager().registerEvents(new RegionListener(), this);
        Bukkit.getPluginManager().registerEvents(new ScriptListener(), this);
        Bukkit.getPluginManager().registerEvents(new BauScoreboard(), this);
        Bukkit.getPluginManager().registerEvents(new ClipboardListener(), this);
        Bukkit.getPluginManager().registerEvents(new CommandGUI(), this);
        Bukkit.getPluginManager().registerEvents(new DetonatorListener(), this);
        Bukkit.getPluginManager().registerEvents(new ItemFrameListener(), this);
        new AFKStopper();

        autoShutdown = Bukkit.getScheduler().runTaskLater(this, Bukkit::shutdown, 1200);
        TPSUtils.init();
    }

    @Override
    public void onDisable() {
        Region.save();
    }

    public static BauSystem getPlugin() {
        return plugin;
    }

    public static UUID getOwner() {
        return SteamwarUser.get(getOwnerID()).getUUID();
    }

    public static int getOwnerID() {
        //Lazy loading to improve startup time of the server in 1.15
        if (owner == null) {
            owner = BauServerInfo.getOwnerId();
        }
        return owner;
    }

    @EventHandler
    public void onDeath(PlayerDeathEvent e) {
        e.setDeathMessage(null);
    }

    @EventHandler
    public void onJoin(PlayerLoginEvent e) {
        if (autoShutdown != null) {
            autoShutdown.cancel();
            autoShutdown = null;
        }

        Player p = e.getPlayer();
        p.setOp(true);
    }

    @EventHandler
    public void onLeave(PlayerQuitEvent e) {
        Player p = e.getPlayer();
        SWScoreboard.impl.removeScoreboard(p);
        if (Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().size() == 1 && Bukkit.getOnlinePlayers().contains(p))) {
            if (autoShutdown != null) {
                autoShutdown.cancel();
            }
            CommandTPSLimiter.setTPS(20.0);
            autoShutdown = Bukkit.getScheduler().runTaskTimer(this, new Runnable() {
                int count = 0;

                @Override
                public void run() {
                    if (count >= 300) {
                        Bukkit.shutdown();
                        return;
                    }
                    count++;
                    try {
                        if (RamUsage.getUsage() > 0.8) {
                            Bukkit.shutdown();
                        }
                    } catch (Throwable throwable) {
                        Bukkit.getLogger().log(Level.WARNING, throwable.getMessage(), throwable);
                        Bukkit.shutdown();
                    }
                }
            }, 20, 20);
        }
    }

    @EventHandler
    public void onInventoryClick(InventoryClickEvent e) {
        ItemStack stack = e.getCursor();
        if (stack == null || !stack.hasItemMeta())
            return;
        assert stack.getItemMeta() != null;
        if (stack.getItemMeta().hasEnchants()) {
            for (Enchantment en : Enchantment.values()) {
                if (stack.getEnchantmentLevel(en) > en.getMaxLevel())
                    stack.removeEnchantment(en);
            }
        }

        Material material = stack.getType();
        if (material == Material.POTION || material == Material.SPLASH_POTION || material == Material.LINGERING_POTION) {
            stack.setType(Material.MILK_BUCKET);
        }

        e.setCurrentItem(stack);
    }
}
