package de.winniepat.citrus.draggui;

import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.entity.effect.*;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class HudRenderer {

    public static void register() {
        HudRenderCallback.EVENT.register((context, tickCounter) -> {
            MinecraftClient client = MinecraftClient.getInstance();
            if (client.player == null || client.options.hudHidden) return;

            HudConfig c = HudConfig.INSTANCE;
            float scale = c.uiScale <= 0 ? 1.0f : c.uiScale;

            if (scale != 1.0f) {
                context.getMatrices().push();
                context.getMatrices().scale(scale, scale, 1f);
            }

            if (c.fpsEnabled) {
                renderFPS(client, context, c.fpsX, c.fpsY, c.fpsColor);
            }
            if (c.pingEnabled) {
                renderPing(client, context, c.pingX, c.pingY, c.pingColor);
            }
            if (c.serverEnabled) {
                renderServer(client, context, c.serverX, c.serverY, c.serverColor);
            }
            if (c.keyEnabled) {
                renderKeystrokes(client, context, c.keyX, c.keyY, c.keyColor);
            }
            if (c.armorEnabled) {
                renderArmorStatus(client, context, c.armorX, c.armorY, c.armorColor);
            }
            if (c.potionEnabled) {
                renderPotionEffects(client, context, c.potionX, c.potionY, c.potionColor);
            }

            if (scale != 1.0f) {
                context.getMatrices().pop();
            }

        });
    }

    private static void renderKeystrokes(MinecraftClient client, DrawContext context, int x, int y, int color) {
        drawKey(context, x + 22, y, "W", client.options.forwardKey.isPressed(), color);
        drawKey(context, x, y + 22, "A", client.options.leftKey.isPressed(), color);
        drawKey(context, x + 22, y + 22, "S", client.options.backKey.isPressed(), color);
        drawKey(context, x + 44, y + 22, "D", client.options.rightKey.isPressed(), color);

        drawKeyCustom(context, x, y + 44, 31, 20, "LMB", client.options.attackKey.isPressed(), color);
        drawKeyCustom(context, x + 33, y + 44, 31, 20, "RMB", client.options.useKey.isPressed(), color);

        drawKeyCustom(context, x, y + 66, 31, 20, "Shf", client.options.sneakKey.isPressed(), color);
        drawKeyCustom(context, x + 33, y + 66, 31, 20, "Jmp", client.options.jumpKey.isPressed(), color);
    }

    private static void drawKey(DrawContext context, int x, int y, String key, boolean pressed, int color) {
        int bgColor = pressed ? 0x99FFFFFF : 0x44000000;
        int textColor = pressed ? 0xFF000000 : color;
        context.fill(x, y, x + 20, y + 20, bgColor);
        context.drawText(MinecraftClient.getInstance().textRenderer, key, x + 7, y + 6, textColor, false);
    }

    private static void drawKeyCustom(DrawContext context, int x, int y, int w, int h, String name, boolean down, int color) {
        int bgColor = down ? 0x99FFFFFF : 0x44000000;
        int textColor = down ? 0xFF000000 : color;
        context.fill(x, y, x + w, y + h, bgColor);
        int labelWidth = MinecraftClient.getInstance().textRenderer.getWidth(name);
        context.drawText(MinecraftClient.getInstance().textRenderer, name, x + (w / 2) - (labelWidth / 2), y + (h / 2) - 4, textColor, false);
    }

    private static void renderFPS(MinecraftClient client, DrawContext context, int x, int y, int color) {
        context.drawText(client.textRenderer, client.getCurrentFps() + " FPS", x, y, color, true);
    }

    private static void renderPing(MinecraftClient client, DrawContext context, int x, int y, int color) {
        int ping = 0;
        if (client.getNetworkHandler() != null) {
            var entry = client.getNetworkHandler().getPlayerListEntry(client.player.getUuid());
            if (entry != null) ping = entry.getLatency();
        }
        context.drawText(client.textRenderer, ping + "ms", x, y, color, true);
    }

    private static void renderServer(MinecraftClient client, DrawContext context, int x, int y, int color) {
        String server = client.getCurrentServerEntry() != null ? client.getCurrentServerEntry().address : "Singleplayer";
        context.drawText(client.textRenderer, server, x, y, color, true);
    }

    private static void renderArmorStatus(MinecraftClient client, DrawContext context, int x, int y, int color) {
        int offset = 0;
        boolean hasArmor = false;
        List<ItemStack> armor = new ArrayList<>();
        client.player.getArmorItems().forEach(armor::add);

        for (int i = 3; i >= 0; i--) {
            ItemStack stack = armor.get(i);
            if (stack.isEmpty()) continue;
            hasArmor = true;
            context.drawItem(stack, x, y + offset);
            context.drawItemInSlot(client.textRenderer, stack, x, y + offset);
            offset += 18;
        }
        if (!hasArmor) {
            context.drawText(client.textRenderer, "[Armor Status]", x, y, color, true);
        }
    }

    private static void renderPotionEffects(MinecraftClient client, DrawContext context, int x, int y, int configColor) {
        assert client.player != null;
        Collection<StatusEffectInstance> effects = client.player.getStatusEffects();
        if (effects.isEmpty()) {
            context.drawText(client.textRenderer, "[Potion Effects]", x, y, configColor, true);
        } else {
            int potionOffset = 0;
            for (var instance : effects) {
                int durationSeconds = instance.getDuration() / 20;
                String time = String.format("%d:%02d", durationSeconds / 60, durationSeconds % 60);
                String name = Text.translatable(instance.getTranslationKey()).getString();
                String level = instance.getAmplifier() > 0 ? " " + (instance.getAmplifier() + 1) : "";
                var effect = instance.getEffectType().value();
                String fullText = name + level + " (" + time + ")";

                int color = (configColor == -1 || configColor == 0xFFFFFF) ?
                        (effect.getCategory() == StatusEffectCategory.BENEFICIAL ? 0x55FF55 : 0xFF5555) : configColor;

                context.drawText(client.textRenderer, fullText, x, y + potionOffset, color, true);
                potionOffset += 12;
            }
        }
    }
}