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

import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.command.SWCommand;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.Barrel;
import org.bukkit.block.BlockState;
import org.bukkit.block.Chest;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;

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

@Linked
public class InventoryFillerCommand extends SWCommand {

    private static final Map<Integer, Integer> POWER_TO_FILLLEVEL = new HashMap<>();

    static {
        POWER_TO_FILLLEVEL.put(0, 0);
        POWER_TO_FILLLEVEL.put(1, 1);
        POWER_TO_FILLLEVEL.put(2, 1 * 64 + 60);
        POWER_TO_FILLLEVEL.put(3, 3 * 64 + 55);
        POWER_TO_FILLLEVEL.put(4, 5 * 64 + 51);
        POWER_TO_FILLLEVEL.put(5, 7 * 64 + 46);
        POWER_TO_FILLLEVEL.put(6, 9 * 64 + 42);
        POWER_TO_FILLLEVEL.put(7, 11 * 64 + 37);
        POWER_TO_FILLLEVEL.put(8, 13 * 64 + 32);
        POWER_TO_FILLLEVEL.put(9, 15 * 64 + 28);
        POWER_TO_FILLLEVEL.put(10, 17 * 64 + 23);
        POWER_TO_FILLLEVEL.put(11, 19 * 64 + 19);
        POWER_TO_FILLLEVEL.put(12, 21 * 64 + 14);
        POWER_TO_FILLLEVEL.put(13, 23 * 64 + 10);
        POWER_TO_FILLLEVEL.put(14, 25 * 64 + 5);
        POWER_TO_FILLLEVEL.put(15, 27 * 64 + 0);
    }

    public InventoryFillerCommand() {
        super("inventoryfill");
    }

    @Register(description = {"INVENTORY_FILL_HELP", "INVENTORY_FILL_INFO"})
    public void toggle(Player player) {
        boolean inventoryFill = Config.getInstance().get(player).getPlainValueOrDefault("inventoryfill", false);
        Config.getInstance().get(player).put("inventoryfill", !inventoryFill);
        if (!inventoryFill) {
            SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("INVENTORY_FILL_ENABLE", player));
            BauSystem.MESSAGE.send("INVENTORY_FILL_INFO", player);
        } else {
            SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("INVENTORY_FILL_DISABLE", player));
        }
    }

    @Register("gui")
    public void gui(Player player) {
        SWInventory inventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_NAME", player));
        inventory.setItem(0, new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 0)).setAmount(1));
        inventory.setItem(1, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 1)).setAmount(1));
        inventory.setItem(2, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 2)).setAmount(2));
        inventory.setItem(3, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 3)).setAmount(3));
        inventory.setItem(4, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 4)).setAmount(4));
        inventory.setItem(5, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 5)).setAmount(5));
        inventory.setItem(6, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 6)).setAmount(6));
        inventory.setItem(7, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 7)).setAmount(7));
        inventory.setItem(8, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 8)).setAmount(8));
        inventory.setItem(9, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 9)).setAmount(9));
        inventory.setItem(10, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 10)).setAmount(10));
        inventory.setItem(11, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 11)).setAmount(11));
        inventory.setItem(12, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 12)).setAmount(12));
        inventory.setItem(13, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 13)).setAmount(13));
        inventory.setItem(14, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 14)).setAmount(14));
        inventory.setItem(15, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 15)).setAmount(15));
        inventory.setItem(17, new SWItem(Material.TNT, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_TNT", player)));

        for (int i = 0; i < 16; i++) {
            inventory.setEventCallback(i, inventoryClickEvent -> {
                selectInventoryType(player, inventoryClickEvent.getCurrentItem().getItemMeta().getDisplayName(), Material.DANDELION, POWER_TO_FILLLEVEL.get(inventoryClickEvent.getCurrentItem().getAmount()));
            });
        }
        inventory.setEventCallback(17, inventoryClickEvent -> {
            selectInventoryType(player, inventoryClickEvent.getCurrentItem().getItemMeta().getDisplayName(), Material.TNT, POWER_TO_FILLLEVEL.get(15));
        });

        inventory.open();
    }

    private final Material[] SHULKER_BOX_MATERIALS = new Material[]{
            Material.SHULKER_BOX,
            Material.WHITE_SHULKER_BOX,
            Material.LIGHT_GRAY_SHULKER_BOX,
            Material.GRAY_SHULKER_BOX,
            Material.BLACK_SHULKER_BOX,
            Material.BROWN_SHULKER_BOX,
            Material.RED_SHULKER_BOX,
            Material.ORANGE_SHULKER_BOX,
            Material.YELLOW_SHULKER_BOX,
            Material.LIME_SHULKER_BOX,
            Material.GREEN_SHULKER_BOX,
            Material.CYAN_SHULKER_BOX,
            Material.LIGHT_BLUE_SHULKER_BOX,
            Material.BLUE_SHULKER_BOX,
            Material.PURPLE_SHULKER_BOX,
            Material.MAGENTA_SHULKER_BOX,
            Material.PINK_SHULKER_BOX
    };

    private void selectInventoryType(Player player, String name, Material material, int count) {
        ItemStack[] itemStacks = new ItemStack[27];
        int index = 0;
        int amount = count;
        while (amount > 0) {
            ItemStack stack;
            if (amount > 64) {
                stack = new ItemStack(material, 64);
                amount -= 64;
            } else {
                stack = new ItemStack(material, amount);
                amount = 0;
            }
            itemStacks[index++] = stack;
        }

        SWInventory inventory = new SWInventory(player, 27, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_NAME", player));
        int i = 0;
        for (Material type : SHULKER_BOX_MATERIALS) {
            inventory.setItemEvent(i++, generateFilledInventory(name, type, itemStacks), inventoryClickEvent -> {
                SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
            });
        }
        inventory.setItemEvent(27 - 6, generateFilledInventory(name, Material.CHEST, itemStacks), inventoryClickEvent -> {
            SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
        });
        inventory.setItemEvent(27 - 4, generateFilledInventory(name, Material.BARREL, itemStacks), inventoryClickEvent -> {
            SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
        });
        inventory.open();
    }

    private ItemStack generateFilledInventory(String name, Material material, ItemStack[] itemStacks) {
        ItemStack itemStack = new ItemStack(material);
        BlockStateMeta meta = (BlockStateMeta) itemStack.getItemMeta();
        BlockState state = meta.getBlockState();

        if (state instanceof ShulkerBox box) {
            box.getInventory().setContents(itemStacks);
            box.update();
            meta.setBlockState(box);
        } else if (state instanceof Chest chest) {
            chest.getInventory().setContents(itemStacks);
            chest.update();
            meta.setBlockState(chest);
        } else if (state instanceof Barrel barrel) {
            barrel.getInventory().setContents(itemStacks);
            barrel.update();
            meta.setBlockState(barrel);
        }
        meta.setDisplayName(name);
        itemStack.setItemMeta(meta);
        return itemStack;
    }
}
