package com.zivilon.cinder_loe.mixins;

import com.zivilon.cinder_loe.world.event.Warband;
import com.zivilon.cinder_loe.world.event.WarbandTracker;
import com.zivilon.cinder_loe.world.event.WarbandLocationInfo;

import lotr.client.gui.LOTRGuiMap;
import lotr.client.gui.LOTRGuiMenuBase;
import lotr.client.LOTRClientProxy;
import lotr.common.LOTRLevelData;
import lotr.common.fac.LOTRFaction;

import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;

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

import org.lwjgl.opengl.GL11;

import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.*;


@Mixin(LOTRGuiMap.class)
public abstract class MixinLOTRGuiMap extends LOTRGuiMenuBase {
    private static Map<UUID, WarbandLocationInfo> warband_locations = WarbandTracker.locations;
    private static ResourceLocation WARBAND_ICON = new ResourceLocation("cinderloe", "textures/gui/alignment.png");

    @Shadow(remap = false)
    private boolean loadingConquestGrid;
    @Shadow(remap = false)
    private boolean hasOverlay;
    @Shadow(remap = false)
    private static int mapXMin;
    @Shadow(remap = false)
    private static int mapXMax;
    @Shadow(remap = false)
    private static int mapYMin;
    @Shadow(remap = false)
    private static int mapYMax;
    @Shadow(remap = false)
    private void drawFancyRect(int x1, int y1, int x2, int y2) {}
    @Shadow(remap = false)
    public float[] transformCoords(float x, float z) { return null;}

    @Inject(method = "func_73863_a", at = @At( value = "INVOKE", target = "renderPlayers(II)V", shift = At.Shift.AFTER), remap = false)
    public void inject_render_warbands(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
        render_warbands(mouseX, mouseY);
    }

    @Dynamic
    private void render_warbands(int cursor_x, int cursor_y) {
        String mouse_over_warband_name = null;
        double mouse_over_warband_x = 0.0D;
        double mouse_over_warband_y = 0.0D;
        double shortest_distance_to_cursor = Double.MAX_VALUE;
        int icon_width_half = 4;
        for (Map.Entry<UUID, WarbandLocationInfo> entry : warband_locations.entrySet()) {
            WarbandLocationInfo info = entry.getValue();
            Warband warband = info.warband;
            String warband_name = warband.faction.warband_name;
            float[] pos = transformCoords((float)info.x, (float)info.z);
            int map_x = Math.round(pos[0]);
            int map_y = Math.round(pos[1]);

            double distance_to_icon = render_warband_icon(warband, map_x, map_y, cursor_x, cursor_y);
            if (distance_to_icon <= (icon_width_half + 3)) {
                if (distance_to_icon <= shortest_distance_to_cursor) {
                    mouse_over_warband_name = StatCollector.translateToLocal(warband_name);
                    mouse_over_warband_x = map_x;
                    mouse_over_warband_y = map_y;
                    shortest_distance_to_cursor = distance_to_icon;
                }
            }
        }
        if (mouse_over_warband_name != null && !this.hasOverlay && !this.loadingConquestGrid) {
            int name_width = this.mc.fontRenderer.getStringWidth(mouse_over_warband_name);
            int name_height = this.mc.fontRenderer.FONT_HEIGHT;
            int namebox_x = (int)Math.round(mouse_over_warband_x);
            int namebox_y = (int)Math.round(mouse_over_warband_y);
            namebox_y += icon_width_half + 3;
            int border = 3;
            int namebox_width = name_width + border * 2;
            namebox_x -= namebox_width / 2;
            int namebox_height = name_height + border * 2;
            int map_border = 2;
            namebox_x = Math.max(namebox_x, mapXMin + map_border);
            namebox_x = Math.min(namebox_x, mapXMax - map_border - namebox_width);
            namebox_y = Math.max(namebox_y, mapYMin + map_border);
            namebox_y = Math.min(namebox_y, mapYMax - map_border - namebox_height);
            GL11.glTranslatef(0.0F, 0.0F, 300.0F);
            drawFancyRect(namebox_x, namebox_y, namebox_x + namebox_width, namebox_y + namebox_height);
            this.mc.fontRenderer.drawString(mouse_over_warband_name, namebox_x + border, namebox_y + border, 16777215);
            GL11.glTranslatef(0.0F, 0.0F, -300.0F);
        }
    }

    @Dynamic
    private double render_warband_icon(Warband warband, double map_x, double map_y, int mouse_x, int mouse_y) {
        int icon_half = 4;
        int icon_border = icon_half + 1;

        map_x = Math.max(mapXMin + icon_border, Math.min(mapXMax - icon_border - 1, map_x));
        map_y = Math.max(mapYMin + icon_border, Math.min(mapYMax - icon_border - 1, map_y));

        // Determine ally/enemy icon
        LOTRFaction faction = warband.faction.faction;
        float alignment = LOTRLevelData.getData(mc.thePlayer).getAlignment(faction);
        boolean is_ally = alignment > 0.0F;

        load_warband_icon(is_ally, (int) map_x, (int) map_y);

        // Return mouse distance to icon
        double dx = map_x - mouse_x;
        double dy = map_y - mouse_y;
        return Math.hypot(dx, dy);
    }


    @Dynamic
    private void load_warband_icon(boolean ally, int x, int y) {
        mc.getTextureManager().bindTexture(LOTRClientProxy.alignmentTexture);
        GL11.glColor4f(1F, 1F, 1F, 1F);
        int variant = ally ? 16 : 0;
        drawTexturedModalRect(x - 8, y - 8, variant, 228, 16, 16);
    }

}
