/*
 *   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.script.lua.libs;

import de.steamwar.bausystem.BauSystem;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.VarArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Linked
public class InventoryLib implements LuaLib {
    @Override
    public String name() {
        return "inventory";
    }

    @Override
    public LuaTable get(Player player) {
        LuaTable inventoryLib = new LuaTable();
        inventoryLib.set("create", new TwoArgFunction() {
            @Override
            public LuaValue call(LuaValue arg1, LuaValue arg2) {
                String title = arg1.checkjstring();
                int size = arg2.checkint();
                SWInventory inventory = new SWInventory(player, size * 9, ChatColor.translateAlternateColorCodes('&', title));
                LuaTable table = new LuaTable();
                table.set("setItem", new VarArgFunction() {
                    @Override
                    public Varargs invoke(Varargs args) {
                        BauSystem.MESSAGE.send("SCRIPT_DEPRECATED", player, "inventory.setItem", "inventory.item");
                        int slot = args.checkint(1);
                        Material material = SWItem.getMaterial(args.checkjstring(2));
                        String name = ChatColor.translateAlternateColorCodes('&', args.checkjstring(3));
                        SWItem item = new SWItem(material, name);

                        if (args.narg() >= 5) {
                            LuaTable lore = args.checktable(4);
                            List<String> loreList = new ArrayList<>(lore.length());
                            for (int i = 1; i <= lore.length(); i++) {
                                loreList.add(ChatColor.translateAlternateColorCodes('&', lore.get(i).checkjstring()));
                            }
                            item.setLore(loreList);
                        }

                        if (args.narg() >= 6) {
                            item.setEnchanted(args.checkboolean(5));
                        }

                        if (args.narg() >= 7) {
                            item.getItemStack().setAmount(args.checkint(6));
                        }

                        LuaFunction handler = args.checkfunction(args.narg());
                        item.setCallback(clickType -> {
                            try {
                                handler.call(LuaValue.valueOf(clickType.name()));
                            } catch (Exception e) {
                                String[] sp = e.getMessage().split(":");
                                BauSystem.MESSAGE.send("SCRIPT_ERROR_CLICK", player, String.join(":", Arrays.copyOfRange(sp, 1, sp.length)));
                            }
                        });

                        inventory.setItem(slot, item);
                        return LuaValue.NIL;
                    }
                });

                table.set("item", new VarArgFunction() {
                    @Override
                    public Varargs invoke(Varargs args) {
                        int slot = args.checkint(1);
                        Material material = SWItem.getMaterial(args.checkjstring(2));
                        String name = ChatColor.translateAlternateColorCodes('&', args.checkjstring(3));
                        LuaFunction handler = args.checkfunction(4);
                        SWItem item = new SWItem(material, name, clickType -> {
                            try {
                                handler.call(LuaValue.valueOf(clickType.name()));
                            } catch (Exception e) {
                                String[] sp = e.getMessage().split(":");
                                BauSystem.MESSAGE.send("SCRIPT_ERROR_CLICK", player, String.join(":", Arrays.copyOfRange(sp, 1, sp.length)));
                            }
                        });

                        if (args.narg() >= 5) {
                            LuaTable lore = args.checktable(5);
                            List<String> loreList = new ArrayList<>(lore.length());
                            for (int i = 1; i <= lore.length(); i++) {
                                loreList.add(ChatColor.translateAlternateColorCodes('&', lore.get(i).checkjstring()));
                            }
                            item.setLore(loreList);
                        }

                        if (args.narg() >= 6) {
                            item.setEnchanted(args.checkboolean(6));
                        }

                        if (args.narg() >= 7) {
                            item.getItemStack().setAmount(args.checkint(7));
                        }

                        inventory.setItem(slot, item);
                        return LuaValue.NIL;
                    }
                });

                table.set("setCloseHandler", new OneArgFunction() {
                    @Override
                    public LuaValue call(LuaValue arg) {
                        LuaFunction function = arg.checkfunction();
                        inventory.addCloseRunnable(() -> {
                            try {
                                function.call();
                            } catch (Exception e) {
                                String[] sp = e.getMessage().split(":");
                                BauSystem.MESSAGE.send("SCRIPT_ERROR_CLICK", player, String.join(":", Arrays.copyOfRange(sp, 1, sp.length)));
                            }
                        });
                        return LuaValue.NIL;
                    }
                });

                table.set("open", new ZeroArgFunction() {
                    @Override
                    public LuaValue call() {
                        inventory.open();
                        return LuaValue.NIL;
                    }
                });

                return table;
            }
        });
        return inventoryLib;
    }
}
