// OptimizedRocket.java
package com.yourname.rocketplugin;

import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.HashSet;
import java.util.Set;

/**
 * Класс, представляющий оптимизированную ракету для разрушения.
 */
public class OptimizedRocket extends Rocket {

    /**
     * Конструктор OptimizedRocket.
     *
     * @param launcher Игрок, запустивший ракету.
     * @param type     Тип ракеты.
     * @param target   Целевая локация.
     * @param plugin   Главный плагин.
     */
    public OptimizedRocket(Player launcher, RocketType type, Location target, RocketPlugin plugin) {
        super(launcher, type, target, plugin);
    }

    @Override
    protected void explode() {
        final World world = this.target.getWorld();
        if (world == null) {
            this.launcher.sendMessage("§cОшибка: Целевая локация не найдена.");
            return;
        }

        if (type.getName().equalsIgnoreCase("USSR")) {
            performUSSRExplosion(world);
        } else {
            super.explode();
        }
    }

    /**
     * Выполняет взрыв для ракеты типа "USSR" с большой областью и огнём.
     *
     * @param world Мир, в котором происходит взрыв.
     */
    private void performUSSRExplosion(World world) {
        final Location center = this.target.clone();
        final double radius = 512.0; // Радиус взрыва

        // Создаем визуальные эффекты взрыва
        world.spawnParticle(this.type.getExplosionParticle(), center, 100, radius / 100, radius / 100, radius / 100, 0.05);
        world.playSound(center, this.type.getExplosionSound(), 10.0F, 1.0F);

        // Обработка большого количества блоков по частям для оптимизации
        new BukkitRunnable() {
            private int currentX = (int) (center.getX() - radius);
            private final int startX = (int) (center.getX() - radius);
            private final int endX = (int) (center.getX() + radius);
            private final int step = 10; // Количество блоков по X для обработки за тик
            private final Set<Block> affectedBlocks = new HashSet<>();

            @Override
            public void run() {
                for (int x = currentX; x < currentX + step && x <= endX; x++) {
                    for (int y = (int) (center.getY() - radius); y <= (int) (center.getY() + radius); y++) {
                        for (int z = (int) (center.getZ() - radius); z <= (int) (center.getZ() + radius); z++) {
                            Location blockLoc = new Location(world, x, y, z);
                            if (blockLoc.distance(center) <= radius) {
                                Block block = world.getBlockAt(blockLoc);
                                if (!affectedBlocks.contains(block)) {
                                    // Устанавливаем блок в огонь
                                    block.setType(Material.FIRE, false);
                                    affectedBlocks.add(block);
                                }
                            }
                        }
                    }
                }
                currentX += step;
                // Добавляем огненные частицы
                world.spawnParticle(Particle.FLAME, center, 500, radius / 50, radius / 50, radius / 50, 0.01);
                world.spawnParticle(Particle.LAVA, center, 300, radius / 50, radius / 50, radius / 50, 0.005);

                // Проверяем завершение
                if (currentX > endX) {
                    this.cancel();
                    world.playSound(center, Sound.ENTITY_GENERIC_EXPLODE, 10.0F, 1.0F);
                    world.createExplosion(center, 0.0F, false, false); // Визуальный эффект без разрушения
                    Bukkit.broadcastMessage("§cРакета USSR взорвалась, все вокруг в огне!");
                }
            }
        }.runTaskTimer(this.plugin, 0L, 1L); // Запускаем с задержкой 0 тиков и периодом 1 тик
    }
}
// PVOBlock.java
package com.yourname.rocketplugin;

import org.bukkit.Location;
import org.bukkit.Material;

import java.util.Set;
import java.util.UUID;

/**
 * Класс, представляющий ПВО блок.
 */
public class PVOBlock {
    private final Location location;
    private final Set<UUID> excludedPlayers;
    private final PVOTypes type;

    /**
     * Конструктор PVOBlock.
     *
     * @param location         Локация блока.
     * @param excludedPlayers Множество UUID игроков, исключённых из защиты.
     * @param type             Тип ПВО.
     */
    public PVOBlock(Location location, Set<UUID> excludedPlayers, PVOTypes type) {
        this.location = location;
        this.excludedPlayers = excludedPlayers;
        this.type = type;
    }

    public Location getLocation() {
        return location;
    }

    public Set<UUID> getExcludedPlayers() {
        return excludedPlayers;
    }

    public PVOTypes getType() {
        return type;
    }

    /**
     * Возвращает материал блока ПВО в зависимости от типа.
     *
     * @return Материал блока.
     */
    public Material getMaterial() {
        switch (type) {
            case BASIC:
                return Material.BEACON;
            case ADVANCED:
                return Material.END_CRYSTAL;
            case ELITE:
                return Material.LODESTONE;
            case PREMIUM:
                return Material.CRYING_OBSIDIAN;
            case ULTIMATE:
                return Material.NETHER_STAR;
            default:
                return Material.BEACON;
        }
    }

    /**
     * Перечисление типов ПВО.
     */
    public enum PVOTypes {
        BASIC,
        ADVANCED,
        ELITE,
        PREMIUM,
        ULTIMATE
    }
}
// PVOCommand.java
package com.yourname.rocketplugin;

import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.Arrays;

/**
 * Класс обработки команды /pvo.
 */
public class PVOCommand implements CommandExecutor {
    private final RocketManager rocketManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор PVOCommand.
     *
     * @param rocketManager Менеджер ракет и ПВО.
     * @param plugin        Главный плагин.
     */
    public PVOCommand(RocketManager rocketManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.plugin = plugin;
    }

    /**
     * Обработка команды /pvo.
     *
     * @param sender  Отправитель команды.
     * @param command Команда.
     * @param label   Ярлык команды.
     * @param args    Аргументы команды.
     * @return Результат выполнения команды.
     */
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        // Проверяем наличие разрешения на использование команды
        if (!sender.hasPermission("pvo.use")) {
            sender.sendMessage(ChatColor.RED + "§cУ вас нет разрешения использовать эту команду.");
            return true;
        }

        // Проверяем, что команда выполняется игроком
        if (!(sender instanceof Player)) {
            sender.sendMessage(ChatColor.RED + "§cТолько игроки могут использовать эту команду.");
            return true;
        }

        Player player = (Player) sender;

        // Проверяем наличие подкоманды
        if (args.length == 0) {
            player.sendMessage(ChatColor.RED + "§cИспользование: /pvo <give|exclude|remove>");
            player.sendMessage(ChatColor.YELLOW + "§eДоступные типы ПВО: BASIC, ADVANCED, ELITE, PREMIUM, ULTIMATE");
            return true;
        }

        String subcommand = args[0].toLowerCase();

        switch (subcommand) {
            case "give":
                handleGive(player, args);
                break;
            case "exclude":
                handleExclude(player, args);
                break;
            case "remove":
                handleRemove(player, args);
                break;
            default:
                player.sendMessage(ChatColor.RED + "§cНеизвестная подкоманда. Используйте /pvo <give|exclude|remove>");
        }

        return true;
    }

    /**
     * Обработка подкоманды give.
     *
     * @param player Игрок, использующий команду.
     * @param args   Аргументы команды.
     */
    private void handleGive(Player player, String[] args) {
        // Проверяем наличие разрешения на выдачу ПВО блоков
        if (!player.hasPermission("pvo.give")) {
            player.sendMessage(ChatColor.RED + "§cУ вас нет разрешения выдавать ПВО блоки.");
            return;
        }

        // Проверяем наличие аргумента типа
        if (args.length < 2) {
            player.sendMessage(ChatColor.RED + "§cИспользование: /pvo give <type>");
            player.sendMessage(ChatColor.YELLOW + "§eДоступные типы ПВО: BASIC, ADVANCED, ELITE, PREMIUM, ULTIMATE");
            return;
        }

        String typeStr = args[1].toUpperCase();
        PVOBlock.PVOTypes type;
        try {
            type = PVOBlock.PVOTypes.valueOf(typeStr);
        } catch (IllegalArgumentException e) {
            player.sendMessage(ChatColor.RED + "§cНеверный тип ПВО. Доступные типы: BASIC, ADVANCED, ELITE, PREMIUM, ULTIMATE");
            return;
        }

        // Определяем материал в зависимости от типа ПВО
        Material material = type.getMaterial();

        // Создаём ItemStack соответствующего типа ПВО
        ItemStack pvoItem = new ItemStack(material);
        ItemMeta meta = pvoItem.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(ChatColor.GOLD + "§lПВО Блок (" + type.name() + ")");
            meta.setLore(Arrays.asList("§7Тип ПВО: " + type.name()));
            pvoItem.setItemMeta(meta);
        }

        // Добавляем предмет в инвентарь игрока
        player.getInventory().addItem(pvoItem);
        player.sendMessage(ChatColor.GREEN + "§aВы получили ПВО блок (" + type.name() + "). Установите его в мире P_Drilla.");
    }

    /**
     * Обработка подкоманды exclude.
     *
     * @param player Игрок, использующий команду.
     * @param args   Аргументы команды.
     */
    private void handleExclude(Player player, String[] args) {
        if (args.length < 3) {
            player.sendMessage(ChatColor.RED + "§cИспользование: /pvo exclude <add|remove> <player>");
            return;
        }

        String action = args[1].toLowerCase();
        String targetName = args[2];
        Player targetPlayer = plugin.getServer().getPlayerExact(targetName);

        if (targetPlayer == null) {
            player.sendMessage(ChatColor.RED + "§cИгрок не найден или не онлайн.");
            return;
        }

        switch (action) {
            case "add":
                rocketManager.getPvoManager().addExcludedPlayer(player, targetPlayer);
                break;
            case "remove":
                rocketManager.getPvoManager().removeExcludedPlayer(player, targetPlayer);
                break;
            default:
                player.sendMessage(ChatColor.RED + "§cНеизвестное действие. Используйте add или remove.");
        }
    }

    /**
     * Обработка подкоманды remove.
     *
     * @param player Игрок, использующий команду.
     * @param args   Аргументы команды.
     */
    private void handleRemove(Player player, String[] args) {
        // Эта команда не используется напрямую, так как remove покрыто в handleExclude
        player.sendMessage(ChatColor.RED + "§cИспользуйте /pvo exclude <add|remove> <player> для управления исключениями.");
    }
}
// PVOListener.java
package com.yourname.rocketplugin;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.ChatColor;
import org.bukkit.event.inventory.InventoryClickEvent;

import java.util.List;

/**
 * Класс слушателя событий, связанных с ПВО.
 */
public class PVOListener implements Listener {
    private final RocketManager rocketManager;
    private final RocketPlugin plugin;

    /**
     * Конструктор PVOListener.
     *
     * @param rocketManager Менеджер ракет и ПВО.
     * @param plugin        Главный плагин.
     */
    public PVOListener(RocketManager rocketManager, RocketPlugin plugin) {
        this.rocketManager = rocketManager;
        this.plugin = plugin;
    }

    /**
     * Событие размещения блока.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        Player player = event.getPlayer();
        Location loc = event.getBlock().getLocation();

        // Проверяем, является ли размещённый блок типом ПВО
        for (PVOBlock.PVOTypes type : PVOBlock.PVOTypes.values()) {
            Material requiredMaterial = type.getMaterial();

            if (event.getBlock().getType().equals(requiredMaterial)) {
                boolean added = rocketManager.getPvoManager().addPVOBlock(player, loc, type);
                if (!added) {
                    event.setCancelled(true);
                }
                // Удаляем сообщение о размещении блока
                return; // Выход после обнаружения нужного типа
            }
        }
    }

    /**
     * Событие разрушения блока.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        Player player = event.getPlayer();
        Location loc = event.getBlock().getLocation();

        // Проверяем, является ли разрушённый блок ПВО блоком
        if (rocketManager.getPvoManager().removePVOBlock(player, loc)) {
            // Удаляем сообщение о разрушении блока
        }
    }

    /**
     * Событие взаимодействия игрока с блоком (для открытия GUI).
     *
     * @param event Событие.
     */
    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {
        Player player = event.getPlayer();
        Location loc = event.getClickedBlock() != null ? event.getClickedBlock().getLocation() : null;

        if (loc == null) return;

        if (rocketManager.getPvoManager().isPVOBlock(loc)) {
            if (event.getAction().toString().contains("RIGHT_CLICK")) {
                event.setCancelled(true);
                openPVOExclusionMenu(player, loc);
            }
        }
    }

    /**
     * Открывает меню для управления исключениями ПВО.
     *
     * @param player Игрок.
     * @param loc    Локация ПВО блока.
     */
    private void openPVOExclusionMenu(Player player, Location loc) {
        PVOBlock pvoBlock = rocketManager.getPvoManager().getPVOBlock(loc);
        if (pvoBlock == null) return;

        Inventory inv = plugin.getServer().createInventory(null, 9, ChatColor.GOLD + "Управление ПВО");

        // Отображаем список исключенных игроков
        int index = 0;
        for (UUID uuid : pvoBlock.getExcludedPlayers()) {
            Player excluded = plugin.getServer().getPlayer(uuid);
            String name = excluded != null ? excluded.getName() : "Неизвестно";
            ItemStack skull = plugin.getServer().getItemFactory().getItemStack(Material.PLAYER_HEAD);
            skull.setAmount(1);
            skull.getItemMeta().setDisplayName(ChatColor.RED + name + " §c(Исключен)");
            inv.setItem(index++, skull);
        }

        // Добавляем кнопку добавления исключения
        ItemStack addButton = new ItemStack(Material.LIME_STAINED_GLASS_PANE);
        addButton.getItemMeta().setDisplayName(ChatColor.GREEN + "Добавить игрока");
        inv.setItem(8, addButton);

        player.openInventory(inv);
    }

    /**
     * Обработка кликов внутри GUI управления ПВО.
     *
     * @param event Событие клика.
     */
    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        if (!(event.getWhoClicked() instanceof Player player)) return;
        if (!event.getView().getTitle().equals(ChatColor.GOLD + "Управление ПВО")) return;

        event.setCancelled(true);
        int slot = event.getSlot();

        if (slot == 8) { // Кнопка добавления игрока
            player.sendMessage(ChatColor.YELLOW + "Введите имя игрока, которого хотите исключить из ПВО:");
            // Назначить слушатель чата или использовать какой-либо другой механизм для получения ввода
            // Это требует более сложной реализации и может быть добавлено позже
            // Например, использовать AsyncPlayerChatEvent с специальным флагом
        }
    }

    /**
     * Событие взрыва для обработки ПВО.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onExplosionPrime(ExplosionPrimeEvent event) {
        World world = event.getEntity().getWorld();
        if (!world.getName().equalsIgnoreCase("P_Drilla")) {
            event.setCancelled(true);
            return;
        }

        Location explosionLocation = event.getEntity().getLocation();
        double radius = 10.0; // Радиус взрыва

        // Получаем ПВО блоки в радиусе взрыва
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(explosionLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            // Применяем логику защиты
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName()); // Получаем владельца по миру (здесь может потребоваться доработка)
                if (owner != null) {
                    // Логика защиты может быть реализована здесь
                }
            }
        }
    }

    /**
     * Событие нанесения вреда игроку.
     *
     * @param event Событие.
     */
    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (!(event.getEntity() instanceof Player damaged)) return;

        Location damageLocation = damaged.getLocation();
        double radius = 10.0; // Радиус действия ПВО

        // Получаем ПВО блоки в радиусе действия от повреждения
        List<PVOBlock> nearbyPVO = rocketManager.getPvoManager().getPVOBlocksInRadius(damageLocation, radius);

        if (!nearbyPVO.isEmpty()) {
            // Проверяем, имеет ли ПВО блока право защищать повреждённого
            for (PVOBlock block : nearbyPVO) {
                Player owner = plugin.getServer().getPlayer(block.getLocation().getWorld().getName()); // Получаем владельца по миру
                if (owner != null) {
                    if (block.getExcludedPlayers().contains(damaged.getUniqueId())) {
                        // Игрок в списке исключений, защита не применяется
                        continue;
                    }

                    if (!damaged.equals(owner)) {
                        // Отменяем урон, если повреждённый не владелец ПВО
                        event.setCancelled(true);
                        damaged.sendMessage(ChatColor.YELLOW + "§eВаш ПВО блок защитил вас от урона!");
                        break;
                    }
                }
            }
        }
    }
}