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

import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;

public class SWItem {

    private ItemStack itemStack;
    private ItemMeta itemMeta;
    private InvCallback callback;

    public static SWItem getPlayerSkull(OfflinePlayer player) {
        return getPlayerSkull(player.getName());
    }

    public static SWItem getPlayerSkull(String playerName) {
        SWItem p = new SWItem();
        ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
        head.editMeta(SkullMeta.class, skullMeta -> {
            try {
                OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName.startsWith(".") ? playerName.substring(1) : playerName);
                PlayerProfile playerProfile = offlinePlayer.getPlayerProfile();
                playerProfile.complete();
                skullMeta.setPlayerProfile(playerProfile);
            } catch (Exception e) {
                // Ignore
            }
        });
        p.setItemStack(head);
        return p;
    }

    public static Material getMaterial(String material) {
        try {
            return Material.valueOf(material);
        } catch (IllegalArgumentException e) {
            return Material.BARRIER;
        }
    }

    public SWItem() {
        itemStack = new ItemStack(Material.AIR);
        itemMeta = itemStack.getItemMeta();
        hideAttributes();
    }

    public SWItem(Material material, String name) {
        this(material, (byte) 0, name, new ArrayList<>(), false, null);
    }

    public SWItem(Material material, String name, InvCallback c) {
        this(material, (byte) 0, name, new ArrayList<>(), false, c);
    }

    public SWItem(Material material, byte meta, String name) {
        this(material, meta, name, new ArrayList<>(), false, null);
    }

    public SWItem(Material material, byte meta, String name, InvCallback c) {
        this(material, meta, name, new ArrayList<>(), false, c);
    }

    public SWItem(Material material, String name, List<String> lore, boolean enchanted, InvCallback c) {
        this(material, (byte) 0, name, lore, enchanted, c);
    }

    @SuppressWarnings("deprecation")
    public SWItem(Material material, byte meta, String name, List<String> lore, boolean enchanted, InvCallback c) {

        try {
            itemStack = new ItemStack(material, 1, (short) 0, meta);
        } catch (IllegalArgumentException e) {
            itemStack = new ItemStack(material, 1);
        }

        itemMeta = itemStack.getItemMeta();

        if (itemMeta != null) {
            hideAttributes();

            itemMeta.setDisplayName(name);
            if (lore != null && !lore.isEmpty()) itemMeta.setLore(lore);
            if (enchanted) itemMeta.addEnchant(Enchantment.UNBREAKING, 10, true);
            itemStack.setItemMeta(itemMeta);
        }
        callback = c;
    }

    public static SWItem getItemFromJson(JsonObject itemJson) {
        SWItem item = null;
        try {
            item = new SWItem(SWItem.getMaterial(itemJson.get("material").getAsString()), itemJson.get("title").getAsString());
        } catch (IllegalArgumentException e) {
            item = new SWItem(Material.STONE, itemJson.get("title").getAsString());
        }
        if (itemJson.has("skullOwner")) {
            item = SWItem.getPlayerSkull(itemJson.get("skullOwner").getAsString());
            item.setName(itemJson.get("title").getAsString());
        }

        if (itemJson.has("enchanted")) {
            item.setEnchanted(true);
        }
        if (itemJson.has("lore")) {
            List<String> lore = new ArrayList<>();
            JsonArray loreArray = itemJson.getAsJsonArray("lore");
            loreArray.forEach(jsonElement -> lore.add(jsonElement.getAsString()));
            item.setLore(lore);
        }

        if (itemJson.has("customModelData")) {
            item.setCustomModelData(itemJson.get("customModelData").getAsInt());
        }
        return item;
    }

    private SWItem hideAttributes() {
        if (itemMeta == null) return this;
        for (ItemFlag flag : EnumSet.allOf(ItemFlag.class)) {
            itemMeta.addItemFlags(flag);
        }
        return this;
    }

    public ItemStack getItemStack() {
        return itemStack;
    }

    public SWItem setItemStack(ItemStack itemStack) {
        this.itemStack = itemStack;
        itemMeta = itemStack.getItemMeta();
        hideAttributes();
        return this;
    }

    public ItemMeta getItemMeta() {
        return itemMeta;
    }

    public SWItem setItemMeta(ItemMeta itemMeta) {
        this.itemMeta = itemMeta;
        itemStack.setItemMeta(itemMeta);
        hideAttributes();
        return this;
    }

    public InvCallback getCallback() {
        return callback;
    }

    public SWItem setCallback(InvCallback callback) {
        this.callback = callback;
        return this;
    }

    public SWItem setName(String name) {
        itemMeta.setDisplayName(name);
        itemStack.setItemMeta(itemMeta);
        return this;
    }

    public SWItem setLore(List<String> lore) {
        itemMeta.setLore(lore);
        itemStack.setItemMeta(itemMeta);
        return this;
    }

    public SWItem setLore(String... lore) {
        itemMeta.setLore(Arrays.stream(lore).collect(Collectors.toList()));
        itemStack.setItemMeta(itemMeta);
        return this;
    }

    public SWItem setEnchanted(boolean enchanted) {
        if (enchanted) {
            itemMeta.addEnchant(Enchantment.UNBREAKING, 10, true);
        } else {
            itemMeta.removeEnchant(Enchantment.UNBREAKING);
        }
        itemStack.setItemMeta(itemMeta);
        return this;
    }

    public SWItem setCustomModelData(int customModelData) {
        itemMeta.setCustomModelData(customModelData);
        itemStack.setItemMeta(itemMeta);
        return this;
    }

    public SWItem setAmount(int count) {
        itemStack.setAmount(count);
        return this;
    }
}
