package jesse.keeblarcraft.GuiMgr.ShopKeeper;

import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
import jesse.keeblarcraft.Utils.CustomSlot;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.village.Merchant;
import net.minecraft.village.MerchantInventory;
import net.minecraft.village.SimpleMerchant;
import net.minecraft.village.TradeOfferList;

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

public class ShopKeeperHandler extends ScreenHandler {
    private Merchant merchant;
    private ShopKeeperInventory shopKeeperInventory;
    private MerchantInventory merchantInventory;
    ConfigManager config = new ConfigManager();
    String shopName;
    // 0 size is default to prevent null. Inventory expanded later

//    private final DefaultedList<ItemStack> merchantInventory = DefaultedList.ofSize(0, ItemStack.EMPTY);
    private boolean canRefreshTrades = false;
    private boolean isLeveledMerchant = false;
    private int levelAmount = 0;
    private int merchantExperience = 0;
    private Map<Text, Integer> slotIdByName = new HashMap<>(); ///TODO: Is this deprecated? Seems unused
    ShopKeeperSlots allSlots = new ShopKeeperSlots();

    public ShopKeeperHandler(int syncId, PlayerInventory playerInventory) {
        this(syncId, playerInventory, new SimpleMerchant(playerInventory.player));
    }

    public ShopKeeperHandler(int syncId, PlayerInventory playerInventory, Merchant merchant) {
        super(ScreenHandlerRegistration.SHOP_KEEPER_HANDLER_SCREEN_HANDLER_TYPE, syncId);
        this.shopName = playerInventory.player.getEntityName(); ///TODO: Needs to be pulled from a shop manager
        this.merchant = merchant;
        this.merchantInventory = new MerchantInventory(merchant);
        merchantInventory.onOpen(playerInventory.player); // not sure if this is doing anything
        this.shopKeeperInventory = new ShopKeeperInventory(merchantInventory);
        addPlayerHotbar(playerInventory);
        RegisterSlots();
    }

    public ShopKeeperInventory GetInventory() {
        String name = "shops/" + shopName;
        if (config.DoesFileExist(name)) {
            ///  TODO: Add system to pull json shop stuff
            System.out.println("Shop exists.");
        } else {
            System.out.println("[NOWARN]: ShopKeep inventory not found for this shop. Creating one...");
            config.CreateFile(name);
        }

        return this.shopKeeperInventory;
    }

    public void RegisterSlots() {
        CustomSlot slotOne = new CustomSlot(this.merchantInventory, 0, 136, 37);


        allSlots.AddSlot("add_item_menu", "add_item_slot", slotOne);
        this.addSlot(slotOne);
    }

    public void showSlot(String menuName, String slotName) {
        allSlots.ShowSlot(menuName, slotName);
    }

    public void hideSlot(String menuName, String slotName) {
        allSlots.HideSlot(menuName, slotName);
    }

    public CustomSlot getSlot(Text name) {
        System.out.println("Printing slot map");
        for (Slot slot : super.slots) {
            System.out.println("Found slot with id: " + slot.id);
        }

        System.out.println("Printing self stored map");
        for (Map.Entry<Text, Integer> entry : this.slotIdByName.entrySet()) {
            System.out.println("entry set id value: " + "K: " + entry.getKey() + " -> V: " + entry.getValue());
        }

        return (CustomSlot) super.getSlot(slotIdByName.get(name));
    }

    public void SetOffers(TradeOfferList offers) {
        this.merchant.setOffersFromServer(offers);
    }

    public void SetExperienceLevel(int xp) {
        this.merchantExperience = xp;
    }

    public void SetLevelProgress(int level) {
        this.levelAmount = level;
    }

    public void SetLeveled(boolean leveled) {
        this.isLeveledMerchant = leveled;
    }

    public void SetCanRefreshTrades(boolean isRefreshable) {
        this.canRefreshTrades = isRefreshable;
    }

    // This is just for SHIFT+CLICK moving
    @Override
    public ItemStack quickMove(PlayerEntity player, int invSlot) {
        System.out.println("Is client: " + player.getWorld().isClient());
        ItemStack newStack = ItemStack.EMPTY;
        Slot slot = this.slots.get(invSlot);
        if (slot.hasStack()) {
            ItemStack originalStack = slot.getStack();
            newStack = originalStack.copy();

            // TODO: This is from the YT video and it looks atrocious. Refactor this later
            if ((invSlot < this.merchantInventory.size() && !this.insertItem(originalStack, this.merchantInventory.size(), this.slots.size(), true)) ||
                    (!this.insertItem(originalStack, 0, this.merchantInventory.size(), false))) {
                return ItemStack.EMPTY;
            }

            if (originalStack.isEmpty()) {
                slot.setStack(ItemStack.EMPTY);
            } else {
                slot.markDirty();;
            }
        }
        return newStack;
    }

    private void addPlayerHotbar(PlayerInventory playerInventory) {
        int spacing = -8;
        for (int i = 0; i < 9; ++i) {
            // int x = (8 + i * 18) + spacing; // Texture draw position
            int x = i * 22 + spacing; // Texture draw position
            int y = 162; // Texture draw position
            this.addSlot(new Slot(playerInventory, i, x, y));
        }
    }

    // Called every tick
    @Override
    public boolean canUse(PlayerEntity player) {
//        System.out.println("canUse called on screen handler");
//        System.out.println("Can player use? " + this.merchantInventory.canPlayerUse(player));
//        System.out.println("Current customer is : " + this.merchantInventory.);
        return true;
    }
}
