#include "pch.h"

#include "MultiSelectionBoxRenderer.h"
#include <cmath>
#include <algorithm>
#include <iostream>

namespace Vivid2D::Render {
    static constexpr double PI = 3.14159265358979323846;

    // -------------------- 配置常量定义 --------------------

    const glm::vec4 MultiSelectionBoxRenderer::DASHED_BORDER_COLOR = glm::vec4(1.0f, 0.85f, 0.0f, 1.0f);
    const glm::vec4 MultiSelectionBoxRenderer::SOLID_BORDER_COLOR_OUTER = glm::vec4(0.0f, 0.85f, 0.95f, 0.12f);
    const glm::vec4 MultiSelectionBoxRenderer::SOLID_BORDER_COLOR_MAIN = glm::vec4(0.0f, 0.92f, 0.94f, 1.0f);
    const glm::vec4 MultiSelectionBoxRenderer::SOLID_BORDER_COLOR_INNER = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f);
    const glm::vec4 MultiSelectionBoxRenderer::HANDLE_COLOR = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
    const glm::vec4 MultiSelectionBoxRenderer::MULTI_SELECTION_HANDLE_COLOR = glm::vec4(1.0f, 0.9f, 0.0f, 1.0f);
    const glm::vec4 MultiSelectionBoxRenderer::CENTER_POINT_COLOR = glm::vec4(1.0f, 0.2f, 0.2f, 1.0f);

    // -------------------- 辅助绘图方法实现 --------------------

    void MultiSelectionBoxRenderer::addFilledQuad(BufferBuilder& bb, float x0, float y0, float x1, float y1) {
        // tri 1
        bb.vertex(x0, y0, 0.0f, 0.0f);
        bb.vertex(x1, y0, 0.0f, 0.0f);
        bb.vertex(x1, y1, 0.0f, 0.0f);
        // tri 2
        bb.vertex(x1, y1, 0.0f, 0.0f);
        bb.vertex(x0, y1, 0.0f, 0.0f);
        bb.vertex(x0, y0, 0.0f, 0.0f);
    }

    void MultiSelectionBoxRenderer::addHandleQuad(BufferBuilder& bb, float cx, float cy, float size) {
        float half = size * 0.5f;
        addFilledQuad(bb, cx - half, cy - half, cx + half, cy + half);
    }

    void MultiSelectionBoxRenderer::addQuadLine(BufferBuilder& bb, float x0, float y0, float x1, float y1, float thickness) {
        float dx = x1 - x0;
        float dy = y1 - y0;
        float len = std::sqrt(dx * dx + dy * dy);

        // 使用一个小的 epsilon 进行浮点数比较
        if (len < 1e-6f) return;

        float halfThick = thickness * 0.5f;
        // 计算法线向量 (nx, ny)
        float nx = -dy / len * halfThick;
        float ny = dx / len * halfThick;

        float v0x = x0 + nx; float v0y = y0 + ny;
        float v1x = x1 + nx; float v1y = y1 + ny;
        float v2x = x1 - nx; float v2y = y1 - ny;
        float v3x = x0 - nx; float v3y = y0 - ny;

        // tri1
        bb.vertex(v3x, v3y, 0.0f, 0.0f);
        bb.vertex(v0x, v0y, 0.0f, 0.0f);
        bb.vertex(v1x, v1y, 0.0f, 0.0f);
        // tri2
        bb.vertex(v1x, v1y, 0.0f, 0.0f);
        bb.vertex(v2x, v2y, 0.0f, 0.0f);
        bb.vertex(v3x, v3y, 0.0f, 0.0f);
    }

    // 假设输入顺序为：p0(x0, y0), p1(x1, y1), p2(x2, y2), p3(x3, y3)
    void MultiSelectionBoxRenderer::addQuadLineLoop(BufferBuilder& bb, float thickness,
        float x0, float y0, float x1, float y1,
        float x2, float y2, float x3, float y3) {
        // 边 1: (x0, y0) -> (x1, y1)
        addQuadLine(bb, x0, y0, x1, y1, thickness);
        // 边 2: (x1, y1) -> (x2, y2)
        addQuadLine(bb, x1, y1, x2, y2, thickness);
        // 边 3: (x2, y2) -> (x3, y3)
        addQuadLine(bb, x2, y2, x3, y3, thickness);
        // 边 4: (x3, y3) -> (x0, y0)
        addQuadLine(bb, x3, y3, x0, y0, thickness);
    }

    void MultiSelectionBoxRenderer::addRing(BufferBuilder& bb, float cx, float cy, float radius, float thickness, int segments) {
        if (segments < 6) segments = 6;
        float halfThick = thickness * 0.5f;
        float innerR = std::max(0.5f, radius - halfThick);
        float outerR = radius + halfThick;

        for (int i = 0; i < segments; i++) {
            // 使用 M_PI (来自 <cmath>)
            float a0 = static_cast<float>(i * 2.0 * PI / segments);
            float a1 = static_cast<float>((i + 1) * 2.0 * PI / segments);

            float cos0 = std::cos(a0), sin0 = std::sin(a0);
            float cos1 = std::cos(a1), sin1 = std::sin(a1);

            float x0i = cx + cos0 * innerR, y0i = cy + sin0 * innerR;
            float x1i = cx + cos1 * innerR, y1i = cy + sin1 * innerR;
            float x0o = cx + cos0 * outerR, y0o = cy + sin0 * outerR;
            float x1o = cx + cos1 * outerR, y1o = cy + sin1 * outerR;

            // tri 1 (x0i, x0o, x1o)
            bb.vertex(x0i, y0i, 0.0f, 0.0f);
            bb.vertex(x0o, y0o, 0.0f, 0.0f);
            bb.vertex(x1o, y1o, 0.0f, 0.0f);
            // tri 2 (x1o, x1i, x0i)
            bb.vertex(x1o, y1o, 0.0f, 0.0f);
            bb.vertex(x1i, y1i, 0.0f, 0.0f);
            bb.vertex(x0i, y0i, 0.0f, 0.0f);
        }
    }

    void MultiSelectionBoxRenderer::addDashedLineVertices(BufferBuilder& bb, float startX, float startY, float endX, float endY,
        float dashLen, float gapLen) {
        float dx = endX - startX;
        float dy = endY - startY;
        float len = std::sqrt(dx * dx + dy * dy);
        if (len < 1e-6f) return;

        float dirX = dx / len, dirY = dy / len;
        float segment = dashLen + gapLen;
        // 使用 std::ceil 和 static_cast
        int count = std::max(1, static_cast<int>(std::ceil(len / segment)));

        for (int i = 0; i < count; i++) {
            float s = i * segment;
            if (s >= len) break;
            float e = std::min(s + dashLen, len);

            float sx = startX + dirX * s;
            float sy = startY + dirY * s;
            float ex = startX + dirX * e;
            float ey = startY + dirY * e;

            // GL_LINES 模式下，每两个顶点构成一条线段
            bb.vertex(sx, sy, 0.0f, 0.0f);
            bb.vertex(ex, ey, 0.0f, 0.0f);
        }
    }

    // -------------------- 公共绘制 API 实现 --------------------

    void MultiSelectionBoxRenderer::drawSelectBox(const BoundingBox& bounds, const glm::vec2& pivot) {
        if (!bounds.isValid()) return;

        float minX = bounds.getMinX();
        float minY = bounds.getMinY();
        float maxX = bounds.getMaxX();
        float maxY = bounds.getMaxY();

        Tesselator& tesselator = Tesselator::getInstance();
        BufferBuilder& bb = tesselator.getBuilder();

        RenderSystem::enableBlend();
        // 使用 GL 常量
        RenderSystem::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        // 估算顶点数：三层边框(3*4*6) + 8个手柄(8*6) + 中心点十字(2*6) + 圆环(18*6)
        int estimatedVertices = (3 * 4 + 8 + 2 + 18) * 6;
        bb.begin(GL_TRIANGLES, estimatedVertices);

        // 外层发光边框
        bb.setColor(SOLID_BORDER_COLOR_OUTER);
        addQuadLineLoop(bb, OUTER_BORDER_THICKNESS, minX, minY, maxX, minY, maxX, maxY, minX, maxY);

        // 主边框
        bb.setColor(SOLID_BORDER_COLOR_MAIN);
        addQuadLineLoop(bb, MAIN_BORDER_THICKNESS, minX, minY, maxX, minY, maxX, maxY, minX, maxY);

        // 内描边
        bb.setColor(SOLID_BORDER_COLOR_INNER);
        addQuadLineLoop(bb, INNER_BORDER_THICKNESS, minX, minY, maxX, minY, maxX, maxY, minX, maxY);

        // 手柄（角点与边中点）
        bb.setColor(HANDLE_COLOR);
        addHandleQuad(bb, minX, minY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, maxX, minY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, minX, maxY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, maxX, maxY, HANDLE_CORNER_SIZE);

        addHandleQuad(bb, (minX + maxX) * 0.5f, minY, HANDLE_MID_SIZE);
        addHandleQuad(bb, (minX + maxX) * 0.5f, maxY, HANDLE_MID_SIZE);
        addHandleQuad(bb, minX, (minY + maxY) * 0.5f, HANDLE_MID_SIZE);
        addHandleQuad(bb, maxX, (minY + maxY) * 0.5f, HANDLE_MID_SIZE);

        // 中心点：十字 + 环
        bb.setColor(CENTER_POINT_COLOR);
        addQuadLine(bb, pivot.x - 6.0f, pivot.y, pivot.x + 6.0f, pivot.y, CENTER_LINE_THICKNESS);
        addQuadLine(bb, pivot.x, pivot.y - 6.0f, pivot.x, pivot.y + 6.0f, CENTER_LINE_THICKNESS);
        addRing(bb, pivot.x, pivot.y, CENTER_RING_RADIUS, CENTER_RING_THICKNESS, 18);

        tesselator.end();
    }

    void MultiSelectionBoxRenderer::drawMultiSelectionBox(const BoundingBox& multiBounds) {
        if (!multiBounds.isValid()) return;

        float minX = multiBounds.getMinX();
        float minY = multiBounds.getMinY();
        float maxX = multiBounds.getMaxX();
        float maxY = multiBounds.getMaxY();

        Tesselator& tesselator = Tesselator::getInstance();
        BufferBuilder& bb = tesselator.getBuilder();

        RenderSystem::enableBlend();
        RenderSystem::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        // 1) 虚线边框（使用 GL_LINES）
        float circumference = 2.0f * (multiBounds.getWidth() + multiBounds.getHeight());
        float segmentLength = DEFAULT_DASH_LENGTH + DEFAULT_GAP_LENGTH;
        int estimatedSegments = std::max(4, static_cast<int>(std::ceil(circumference / segmentLength)));

        // 这里的 GL_LINES 模式应使用 GL_LINES 常量 (假设它被正确定义)
        bb.begin(GL_LINES, estimatedSegments * 8); // 4条边 * 2个顶点/线段 * 估算线段数

        bb.setColor(DASHED_BORDER_COLOR);
        addDashedLineVertices(bb, minX, minY, maxX, minY, DEFAULT_DASH_LENGTH, DEFAULT_GAP_LENGTH);
        addDashedLineVertices(bb, maxX, minY, maxX, maxY, DEFAULT_DASH_LENGTH, DEFAULT_GAP_LENGTH);
        addDashedLineVertices(bb, maxX, maxY, minX, maxY, DEFAULT_DASH_LENGTH, DEFAULT_GAP_LENGTH);
        addDashedLineVertices(bb, minX, maxY, minX, minY, DEFAULT_DASH_LENGTH, DEFAULT_GAP_LENGTH);
        tesselator.end();

        // 2) 手柄与中心（合并为一次三角形绘制）
        bb.begin(GL_TRIANGLES, (8 + 2) * 6); // 8个手柄 + 2个中心十字线段 (转换为四边形)

        bb.setColor(MULTI_SELECTION_HANDLE_COLOR);
        addHandleQuad(bb, minX, minY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, maxX, minY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, minX, maxY, HANDLE_CORNER_SIZE);
        addHandleQuad(bb, maxX, maxY, HANDLE_CORNER_SIZE);

        addHandleQuad(bb, (minX + maxX) * 0.5f, minY, HANDLE_MID_SIZE);
        addHandleQuad(bb, (minX + maxX) * 0.5f, maxY, HANDLE_MID_SIZE);
        addHandleQuad(bb, minX, (minY + maxY) * 0.5f, HANDLE_MID_SIZE);
        addHandleQuad(bb, maxX, (minY + maxY) * 0.5f, HANDLE_MID_SIZE);

        glm::vec2 center = multiBounds.getCenter();
        bb.setColor(CENTER_POINT_COLOR);
        addQuadLine(bb, center.x - 6.0f, center.y, center.x + 6.0f, center.y, CENTER_LINE_THICKNESS);
        addQuadLine(bb, center.x, center.y - 6.0f, center.x, center.y + 6.0f, CENTER_LINE_THICKNESS);

        tesselator.end();
    }

} // namespace com::chuangzhou::vivid2D::render