package jesse.keeblarcraft.gui.ShopKeeperGUI;

import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperHandler;
import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperInventory;
import jesse.keeblarcraft.GuiMgr.ShopKeeper.StoreItem;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.ClientHelpers.Helper;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
import jesse.keeblarcraft.gui.Generics.ClickableLayer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Items;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ShopKeeperMenu extends HandledScreen<ShopKeeperHandler> {
    private static final Identifier MENU_TEXTURE = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/shopkeeper_gui.png");
    private static final Identifier ADD_BUTTON = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/plus.png");
    private static final Identifier SCROLLBAR = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/scrollbar.png");
    private int x = 0;
    private int y = 0;
    private final List<ClickableLayer> layers = new ArrayList<>();
    private MerchandiseScroller catalogue;
    private ShopKeeperInventory serverInventory;
    private Scrollbar scrollbar;

    private static class TextPosition {
        public static Pair<Double, Double> CHECKOUT_PRICE = new Pair<>(100.0, 230.0); // TODO: Probably needs to be tested
    }

    public ShopKeeperMenu(ShopKeeperHandler handler, PlayerInventory inventory, Text title) {
        super(handler, inventory, title);
    }

    @Override
    protected void init() {
        super.init();
        titleY = 1000; //begone from screen
        playerInventoryTitleY = 1000; //begone from screen

        // Set the main shop keeping menu variables here
        this.backgroundWidth = 256;
        this.backgroundHeight = 256;
        this.x = (width - backgroundWidth) / 2;
        this.y = (height - backgroundHeight) / 2;

        // These value are derived from playing around with GUI placement. A better method probably exists; but not right now!
        scrollbar = new Scrollbar(SCROLLBAR, Text.of("scrollbar"), 15, 28, x+243, y+40, y+50, 163);

        // Add all layers below
        AddNewButton(ADD_BUTTON, Text.of("ADD ITEM BUTTON"), x+20, y+20, 8, 8);
        AddNewLayer(scrollbar);




        catalogue = new MerchandiseScroller(null, Text.of("catalogue"), 200, 166, x+45, y+44, this.getScreenHandler().GetInventory());


        // This is for temporary testing
        StoreItem newMerch = new StoreItem("Dirt block", "minecraft:dirt_block", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch2 = new StoreItem("Dirt block2", "minecraft:dirt_block2", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch3 = new StoreItem("Dirt block3", "minecraft:dirt_block3", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch4 = new StoreItem("Dirt block4", "minecraft:dirt_block4", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch5 = new StoreItem("Dirt block5", "minecraft:dirt_block5", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch6 = new StoreItem("Dirt block6", "minecraft:dirt_block6", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch7 = new StoreItem("Dirt block7", "minecraft:dirt_block7", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch8 = new StoreItem("Dirt block8", "minecraft:dirt_block8", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch9 = new StoreItem("Dirt block9", "minecraft:dirt_block9", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch10 = new StoreItem("Dirt block10", "minecraft:dirt_block10", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch11 = new StoreItem("Dirt block11", "minecraft:dirt_block11", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch12 = new StoreItem("Dirt block711", "minecraft:dirt_block12", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch13 = new StoreItem("Dirt block711", "minecraft:dirt_block13", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch14 = new StoreItem("Dirt block711", "minecraft:dirt_block14", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch15 = new StoreItem("Dirt block71", "minecraft:dirt_block15", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch16 = new StoreItem("Dirt block711111", "minecraft:dirt_block16", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch17 = new StoreItem("Dirt block711", "minecraft:dirt_block17", 500.0, Items.DIRT.getDefaultStack());
        StoreItem newMerch18 = new StoreItem("Dirt block711", "minecraft:dirt_block18", 500.0, Items.DIRT.getDefaultStack());


        catalogue.Add(newMerch);
        catalogue.Add(newMerch2);
        catalogue.Add(newMerch3);
        catalogue.Add(newMerch4);
        catalogue.Add(newMerch5);
        catalogue.Add(newMerch6);
        catalogue.Add(newMerch7);
        catalogue.Add(newMerch8);
        catalogue.Add(newMerch9);
        catalogue.Add(newMerch10);
        catalogue.Add(newMerch11);
        catalogue.Add(newMerch12);
        catalogue.Add(newMerch13);
        catalogue.Add(newMerch14);
        catalogue.Add(newMerch15);
        catalogue.Add(newMerch16);
        catalogue.Add(newMerch17);
        catalogue.Add(newMerch18);


        AddNewLayer(catalogue);





        // The GUI can comfortably fit 6 items. If the amount is less; the scrollbar should be disabled from use.
        if (catalogue.Size() <= 6) {
            scrollbar.SetLocked(true);
        }

        System.out.println("This store catalogue has size " + catalogue.Size());
    }

    @Override
    protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
        // Draw the menu texture first
        context.drawTexture(MENU_TEXTURE, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight, this.backgroundWidth, this.backgroundHeight);

        this.getScreenHandler().showSlot("add_item_menu", "add_item_slot");

        catalogue.UpdateScrollAmount(scrollbar.GetScrollDistance());
        if (MinecraftClient.getInstance() != null) {
            // Draw the cart total
            int cartTotalPosX = this.x + TextPosition.CHECKOUT_PRICE.GetKey().intValue();
            int cartTotalPosY = this.y + TextPosition.CHECKOUT_PRICE.GetValue().intValue();
            context.drawText(MinecraftClient.getInstance().textRenderer, Text.of("$" + catalogue.GetCartTotal().toString()), cartTotalPosX, cartTotalPosY, 4, false);
        }

        // Draws primary layers first
        for (ClickableLayer layer : layers) {
            layer.renderButton(context, mouseX, mouseY, delta);
            ToggleSlots(layer.GetLayerName().getString(), layer.GetDrawableSlots());

            // If a primary layer happens to want sub-layers in itself; we draw those here
            for (ClickableLayer subLayer : layer.GetSubLayers()) {
                subLayer.renderButton(context, mouseX, mouseY, delta);
                ToggleSlots(subLayer.GetLayerName().getString(), subLayer.GetDrawableSlots());
            }

            // We only notify the parent to update sub layers. It must manage its own sub layers
            layer.UpdateSubLayers();
        }
    }

    private void ToggleSlots(String menuName, Map<String, Boolean> slotNames) {
        for (Map.Entry<String, Boolean> slot : slotNames.entrySet()) {
            if (slot.getValue()) {
                this.getScreenHandler().showSlot(menuName, slot.getKey());
            } else {
                this.getScreenHandler().hideSlot(menuName, slot.getKey());
            }
        }
    }

    // Takes an image and adds it to the background draw list and saves coordinates to return to a callback if it is clicked
    private void AddNewButton(Identifier iconId, Text layerName, int drawX, int drawY, int imgWidth, int imgHeight) {
        layers.add(new NewItemButton(iconId, layerName, imgWidth, imgHeight, drawX, drawY));
    }

    private void AddNewLayer(ClickableLayer layer) {
        layers.add(layer);
    }

    @Override
     public void drawForeground(DrawContext context, int mouseX, int mouseY) {
         // We override this function to intentionally do nothing
         // If in the future we want, we would draw the foreground and TITLES with this!
     }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        System.out.println("ShopKeeperMenu MX MY: " + mouseX + " " + mouseY);
        for (ClickableLayer layer : layers) {
            // Check main layer first
            if (Helper.WithinBounds(layer.getX(), layer.getY(), layer.getWidth(), layer.getHeight(), mouseX, mouseY)) {
                layer.mouseClicked(mouseX, mouseY, button);
            }

            for (ClickableLayer subLayer : layer.GetSubLayers()) {

                if (subLayer.visible && Helper.WithinBounds(subLayer.getX(), subLayer.getY(), subLayer.getWidth(), subLayer.getHeight(), mouseX, mouseY)) {
                    subLayer.mouseClicked(mouseX, mouseY, button);
                }
            }
        }

        return true;
    }

    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        scrollbar.SetDragging(false);

        for (ClickableLayer layer : layers) {
            // Scrollbar gets special handling above this. Ignore in loop
            if (layer.GetLayerName().getString().equals("scrollbar")) {
                continue;
            }
            // Check main layer first
            if (Helper.WithinBounds(layer.getX(), layer.getY(), layer.getWidth(), layer.getHeight(), mouseX, mouseY)) {
                layer.mouseReleased(mouseX, mouseY, button);
            }

            for (ClickableLayer subLayer : layer.GetSubLayers()) {

                if (subLayer.visible && Helper.WithinBounds(subLayer.getX(), subLayer.getY(), subLayer.getWidth(), subLayer.getHeight(), mouseX, mouseY)) {
                    subLayer.mouseReleased(mouseX, mouseY, button);
                }
            }
        }

        return true;
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
//        System.out.println("Mouse scrolled. Vert amount is: " + verticalAmount);
        scrollbar.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
        return true;
    }



    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
//        super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
        if (scrollbar.IsDragging()) {
            scrollbar.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
        }

        for (ClickableLayer layer : layers) {
            // Scrollbar layer gets special handling above this for loop. Skip here
            if (layer.GetLayerName().getString().equals("scrollbar")) {
                continue;
            }

            // Check main layer first
            if (Helper.WithinBounds(layer.getX(), layer.getY(), layer.getWidth(), layer.getHeight(), mouseX, mouseY)) {
                layer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
            }

            for (ClickableLayer subLayer : layer.GetSubLayers()) {

                if (subLayer.visible && Helper.WithinBounds(subLayer.getX(), subLayer.getY(), subLayer.getWidth(), subLayer.getHeight(), mouseX, mouseY)) {
                    subLayer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
                }
            }
        }

        return true;
    }

    // Check if a click point is within the context of a square (square = x, y, w, h)
//    public static boolean WithinBounds(double x, double y, double w, double h, double clickX, double clickY) {
////        System.out.println("Mouse click X Y: " + clickX + " " + clickY);
////        System.out.println("Rectangle X Y W H: " + x + " " + y + " " + w + " " + h);
//        return (clickX >= x) && (clickX <= x + w) && (clickY >= y) && (clickY <= y + h);
//    }

    @Override
    public void render(DrawContext context, int mouseX, int mouseY, float delta) {
        renderBackground(context, mouseX, mouseY, delta);
        super.render(context, mouseX, mouseY, delta);
        drawMouseoverTooltip(context, mouseX, mouseY);
    }
}
