package top.r3944realms.lib39.client.renderer;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import org.joml.Matrix4f;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

/**
 * 圆形径向菜单渲染器
 * 用于创建美观的圆形选择菜单
 *
 * @param <T> the type parameter
 */
public class RadialMenuRenderer<T> {
    /**
     * The constant DEFAULT_INNER_RADIUS.
     */
// 默认配置常量
    public static final float DEFAULT_INNER_RADIUS = 30f;
    /**
     * The constant DEFAULT_OUTER_RADIUS.
     */
    public static final float DEFAULT_OUTER_RADIUS = 80f;
    /**
     * The constant DEFAULT_MIDDLE_RADIUS.
     */
    public static final float DEFAULT_MIDDLE_RADIUS = 55f;
    /**
     * The constant DEFAULT_SEGMENTS.
     */
    public static final int DEFAULT_SEGMENTS = 64;

    // 配置选项
    private final float innerRadius;
    private final float outerRadius;
    private final float middleRadius;
    private final int segments;
    private final boolean enableHoverAnimation;
    private final ColorScheme colorScheme;

    // 状态
    private int hoveredIndex = -1;
    private final float[] hoverAnimations;
    private long lastAnimationTime = 0;

    /**
     * The type Color scheme.
     */
    public static class ColorScheme {
        /**
         * The Normal color.
         */
        public final float[] normalColor;
        /**
         * The Hovered color.
         */
        public final float[] hoveredColor;
        /**
         * The Selected color.
         */
        public final float[] selectedColor;
        /**
         * The Background color.
         */
        public final float[] backgroundColor;

        /**
         * Instantiates a new Color scheme.
         *
         * @param normalColor     the normal color
         * @param hoveredColor    the hovered color
         * @param selectedColor   the selected color
         * @param backgroundColor the background color
         */
        public ColorScheme(float[] normalColor, float[] hoveredColor, float[] selectedColor, float[] backgroundColor) {
            this.normalColor = normalColor;
            this.hoveredColor = hoveredColor;
            this.selectedColor = selectedColor;
            this.backgroundColor = backgroundColor;
        }

        /**
         * The constant DEFAULT.
         */
// 预定义颜色方案
        public static final ColorScheme DEFAULT = new ColorScheme(
                new float[]{0.3f, 0.3f, 0.8f, 0.6f},  // 正常 - 蓝色
                new float[]{0.9f, 0.7f, 0.1f, 0.8f},  // 悬停 - 金色
                new float[]{0.2f, 0.8f, 0.2f, 0.9f},  // 选中 - 绿色
                new float[]{0.1f, 0.1f, 0.1f, 0.7f}   // 背景
        );

        /**
         * The constant FIRE.
         */
        public static final ColorScheme FIRE = new ColorScheme(
                new float[]{0.8f, 0.3f, 0.1f, 0.6f},  // 正常 - 红色
                new float[]{1.0f, 0.5f, 0.0f, 0.8f},  // 悬停 - 橙色
                new float[]{1.0f, 0.9f, 0.0f, 0.9f},  // 选中 - 黄色
                new float[]{0.2f, 0.1f, 0.0f, 0.7f}   // 背景
        );

        /**
         * The constant NATURE.
         */
        public static final ColorScheme NATURE = new ColorScheme(
                new float[]{0.2f, 0.6f, 0.3f, 0.6f},  // 正常 - 绿色
                new float[]{0.4f, 0.8f, 0.4f, 0.8f},  // 悬停 - 亮绿
                new float[]{0.1f, 0.9f, 0.7f, 0.9f},  // 选中 - 青绿
                new float[]{0.1f, 0.2f, 0.1f, 0.7f}   // 背景
        );
    }


    /**
     * Instantiates a new Radial menu renderer.
     */
    public RadialMenuRenderer() {
        this(DEFAULT_INNER_RADIUS, DEFAULT_OUTER_RADIUS, ColorScheme.DEFAULT);
    }

    /**
     * Instantiates a new Radial menu renderer.
     *
     * @param innerRadius the inner radius
     * @param outerRadius the outer radius
     */
    public RadialMenuRenderer(float innerRadius, float outerRadius) {
        this(innerRadius, outerRadius, ColorScheme.DEFAULT);
    }

    /**
     * Instantiates a new Radial menu renderer.
     *
     * @param innerRadius the inner radius
     * @param outerRadius the outer radius
     * @param colorScheme the color scheme
     */
    public RadialMenuRenderer(float innerRadius, float outerRadius, ColorScheme colorScheme) {
        this(innerRadius, outerRadius, (innerRadius + outerRadius) / 2f, DEFAULT_SEGMENTS, true, colorScheme);
    }

    /**
     * Instantiates a new Radial menu renderer.
     *
     * @param innerRadius          the inner radius
     * @param outerRadius          the outer radius
     * @param middleRadius         the middle radius
     * @param segments             the segments
     * @param enableHoverAnimation the enable hover animation
     * @param colorScheme          the color scheme
     */
    public RadialMenuRenderer(float innerRadius, float outerRadius, float middleRadius,
                              int segments, boolean enableHoverAnimation, ColorScheme colorScheme) {
        this.innerRadius = innerRadius;
        this.outerRadius = outerRadius;
        this.middleRadius = middleRadius;
        this.segments = segments;
        this.enableHoverAnimation = enableHoverAnimation;
        this.colorScheme = colorScheme;
        this.hoverAnimations = new float[0];
    }

    /**
     * 渲染圆形菜单
     *
     * @param guiGraphics   the gui graphics
     * @param entries       the entries
     * @param titleProvider the title provider
     * @param iconProvider  the icon provider
     * @param selectedIndex the selected index
     * @param trackMouse    the track mouse
     */
    public void render(GuiGraphics guiGraphics, List<T> entries,
                       Function<T, Component> titleProvider,
                       Function<T, ItemStack> iconProvider,
                       int selectedIndex, boolean trackMouse) {
        if (entries.isEmpty()) return;

        // 更新动画状态
        updateHoverAnimations(entries.size());

        // 设置渲染状态
        RenderSystem.enableBlend();
        RenderSystem.defaultBlendFunc();
        RenderSystem.setShader(GameRenderer::getPositionColorShader);

        float centerX = guiGraphics.guiWidth() / 2f;
        float centerY = guiGraphics.guiHeight() / 2f;

        guiGraphics.pose().pushPose();
        guiGraphics.pose().translate(centerX, centerY, 0f);

        // 渲染所有扇形区域
        renderSectors(guiGraphics, entries, selectedIndex);

        // 渲染图标和文本
        renderIconsAndText(guiGraphics, entries, titleProvider, iconProvider);

        guiGraphics.pose().popPose();

        RenderSystem.disableBlend();
    }

    /**
     * 渲染扇形区域
     */
    private void renderSectors(GuiGraphics guiGraphics, List<T> entries, int selectedIndex) {
        int count = entries.size();
        float angleSize = 360f / count;

        for (int i = 0; i < count; i++) {
            float startAngle = -90f + i * angleSize;
            float currentOuterRadius = outerRadius;

            // 悬停动画效果
            if (enableHoverAnimation && i < hoverAnimations.length) {
                currentOuterRadius += hoverAnimations[i] * 5f;
            }

            // 颜色设置
            float[] color = getSectorColor(i, selectedIndex, entries.get(i));

            // 绘制扇形
            drawSector(guiGraphics, startAngle, angleSize, innerRadius, currentOuterRadius, color);
        }
    }


    /**
     * 获取扇形颜色
     */
    private float[] getSectorColor(int index, int selectedIndex, T entry) {
        if (index == selectedIndex) {
            return colorScheme.selectedColor; // 选中状态
        } else if (index == hoveredIndex) {
            return colorScheme.hoveredColor;  // 悬停状态
        } else {
            return colorScheme.normalColor;   // 普通状态
        }
    }

    /**
     * 绘制单个扇形
     */
    private void drawSector(GuiGraphics guiGraphics, float startAngle, float angleSize,
                            float innerRadius, float outerRadius, float[] color) {
        BufferBuilder buffer = Tesselator.getInstance().getBuilder();
        buffer.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION_COLOR);

        Matrix4f matrix = guiGraphics.pose().last().pose();
        float segments = Math.max(8, this.segments * (angleSize / 360f));

        for (int i = 0; i <= segments; i++) {
            float progress = i / segments;
            float angle = startAngle + progress * angleSize;
            float rad = angle * Mth.DEG_TO_RAD;

            float cos = Mth.cos(rad);
            float sin = Mth.sin(rad);

            // 外圈顶点
            buffer.vertex(matrix, outerRadius * cos, outerRadius * sin, 0)
                    .color(color[0], color[1], color[2], color[3]).endVertex();
            // 内圈顶点
            buffer.vertex(matrix, innerRadius * cos, innerRadius * sin, 0)
                    .color(color[0], color[1], color[2], color[3] * 0.6f).endVertex();
        }

        BufferUploader.drawWithShader(buffer.end());
    }

    /**
     * 渲染图标和文本
     */
    private void renderIconsAndText(GuiGraphics guiGraphics, List<T> entries,
                                    Function<T, Component> titleProvider,
                                    Function<T, ItemStack> iconProvider) {
        int count = entries.size();
        var font = Minecraft.getInstance().font;

        for (int i = 0; i < count; i++) {
            T entry = entries.get(i);
            float angle = (-90f + 360f * (i + 0.5f) / count) * Mth.DEG_TO_RAD;

            // 计算位置
            float x = Mth.cos(angle) * middleRadius;
            float y = Mth.sin(angle) * middleRadius;

            // 渲染图标
            ItemStack icon = iconProvider.apply(entry);
            if (!icon.isEmpty()) {
                guiGraphics.renderItem(icon, (int)(x - 8), (int)(y - 8));
            }

            // 渲染文本
            Component title = titleProvider.apply(entry);
            guiGraphics.pose().pushPose();
            guiGraphics.pose().translate(x, y + 12, 0);
            guiGraphics.pose().scale(0.7f, 0.7f, 0.7f);
            guiGraphics.drawString(font, title, -font.width(title) / 2, 0, 0xFFFFFF, true);
            guiGraphics.pose().popPose();
        }
    }

    /**
     * 更新悬停动画
     */
    private void updateHoverAnimations(int entryCount) {
        if (!enableHoverAnimation) return;

        long currentTime = System.currentTimeMillis();
        float deltaTime = Math.min((currentTime - lastAnimationTime) / 1000f, 0.1f);
        lastAnimationTime = currentTime;

        // 确保数组大小正确
        if (hoverAnimations.length != entryCount) {
            // 这里需要重新初始化数组，实际使用时应该处理数组大小变化
        }

        // 更新动画值
        for (int i = 0; i < hoverAnimations.length && i < entryCount; i++) {
            if (i == hoveredIndex) {
                hoverAnimations[i] = Mth.clamp(hoverAnimations[i] + deltaTime * 2f, 0f, 1f);
            } else {
                hoverAnimations[i] = Mth.clamp(hoverAnimations[i] - deltaTime * 3f, 0f, 1f);
            }
        }
    }

    /**
     * 获取鼠标下的条目索引
     *
     * @param entries the entries
     * @param mouseX  the mouse x
     * @param mouseY  the mouse y
     * @return the hovered entry
     */
    public int getHoveredEntry(List<T> entries, double mouseX, double mouseY) {
        float centerX = Minecraft.getInstance().getWindow().getGuiScaledWidth() / 2f;
        float centerY = Minecraft.getInstance().getWindow().getGuiScaledHeight() / 2f;

        double relX = mouseX - centerX;
        double relY = mouseY - centerY;
        double distance = Math.sqrt(relX * relX + relY * relY);

        // 检查是否在有效范围内
        if (distance < innerRadius || distance > outerRadius) {
            hoveredIndex = -1;
            return -1;
        }

        // 计算角度
        double angle = Math.atan2(relY, relX) * Mth.RAD_TO_DEG;
        angle = (angle + 450) % 360; // 标准化到 0-360

        int count = entries.size();
        int index = (int) (angle / (360f / count)) % count;

        hoveredIndex = index;
        return index;
    }

    /**
     * 清除状态
     */
    public void clearState() {
        hoveredIndex = -1;
        // 重置动画数组
        Arrays.fill(hoverAnimations, 0f);
    }
}
