package com.trunksbomb.minetriad.client.hud;

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

import com.trunksbomb.minetriad.blockentity.DuelTableBlockEntity;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RenderGuiLayerEvent;

public final class LocalDuelHudOverlay {
    private static final int SCAN_INTERVAL_TICKS = 10;
    private static final int STALE_TIMEOUT_TICKS = 20;
    private static final double MAX_DISTANCE_SQ = 10.0D * 10.0D;

    private static BlockPos trackedTablePos;
    private static int nextScanIn;
    private static int staleTicksRemaining;

    private LocalDuelHudOverlay() {
    }

    public static void onClientTick(ClientTickEvent.Post event) {
        Minecraft minecraft = Minecraft.getInstance();
        if (minecraft.level == null || minecraft.player == null) {
            clear();
            return;
        }

        if (trackedTablePos != null && !isValidTrackedTable(minecraft, trackedTablePos)) {
            clear();
        }

        if (nextScanIn > 0) {
            nextScanIn--;
        } else {
            trackedTablePos = findNearestActiveTable(minecraft);
            nextScanIn = SCAN_INTERVAL_TICKS;
            staleTicksRemaining = trackedTablePos == null ? 0 : STALE_TIMEOUT_TICKS;
        }

        if (trackedTablePos != null) {
            staleTicksRemaining--;
            if (staleTicksRemaining <= 0 && !isValidTrackedTable(minecraft, trackedTablePos)) {
                clear();
            } else if (isValidTrackedTable(minecraft, trackedTablePos)) {
                staleTicksRemaining = STALE_TIMEOUT_TICKS;
            }
        }
    }

    public static void onRenderGui(RenderGuiLayerEvent.Post event) {
        Minecraft minecraft = Minecraft.getInstance();
        if (minecraft.level == null || minecraft.player == null || trackedTablePos == null) {
            return;
        }

        DuelTableBlockEntity table = duelTableAt(minecraft, trackedTablePos);
        if (table == null || !table.hudActive()) {
            return;
        }

        List<Component> lines = new ArrayList<>();
        lines.add(Component.literal("P1 Cards in hand: " + table.hudP1HandCount()));
        lines.add(Component.literal("P2 Cards in hand: " + table.hudP2HandCount()));
        lines.add(Component.literal("Score: " + table.hudP1Score() + ":" + table.hudP2Score()));
        lines.add(Component.literal("Rules: " + table.hudRules()));
        lines.add(Component.literal("Game state: " + table.hudGameState()));
        lines.add(Component.literal("Turn: " + table.hudTurn()));
        lines.add(Component.literal("Next: " + table.hudInstruction()));

        GuiGraphics guiGraphics = event.getGuiGraphics();
        int x = 8;
        int y = 8;
        int lineHeight = 10;
        int width = 0;
        for (Component line : lines) {
            width = Math.max(width, minecraft.font.width(line));
        }
        int height = lines.size() * lineHeight + 8;
        guiGraphics.fill(x - 4, y - 4, x + width + 4, y + height - 4, 0x80000000);
        for (int index = 0; index < lines.size(); index++) {
            guiGraphics.drawString(minecraft.font, lines.get(index), x, y + index * lineHeight, 0xFFFFFF, false);
        }
    }

    private static BlockPos findNearestActiveTable(Minecraft minecraft) {
        BlockPos origin = minecraft.player.blockPosition();
        BlockPos nearest = null;
        double nearestDistance = MAX_DISTANCE_SQ;
        for (BlockPos pos : BlockPos.betweenClosed(origin.offset(-8, -4, -8), origin.offset(8, 4, 8))) {
            DuelTableBlockEntity table = duelTableAt(minecraft, pos);
            if (table == null || !table.hudActive()) {
                continue;
            }
            double distance = pos.distSqr(minecraft.player.blockPosition());
            if (distance <= nearestDistance) {
                nearestDistance = distance;
                nearest = pos.immutable();
            }
        }
        return nearest;
    }

    private static boolean isValidTrackedTable(Minecraft minecraft, BlockPos pos) {
        DuelTableBlockEntity table = duelTableAt(minecraft, pos);
        return table != null
                && table.hudActive()
                && pos.distSqr(minecraft.player.blockPosition()) <= MAX_DISTANCE_SQ;
    }

    private static DuelTableBlockEntity duelTableAt(Minecraft minecraft, BlockPos pos) {
        if (minecraft.level == null) {
            return null;
        }
        BlockEntity blockEntity = minecraft.level.getBlockEntity(pos);
        return blockEntity instanceof DuelTableBlockEntity duelTableBlockEntity ? duelTableBlockEntity : null;
    }

    private static void clear() {
        trackedTablePos = null;
        nextScanIn = 0;
        staleTicksRemaining = 0;
    }
}
