#pragma once
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <stdexcept>

class Math
{
private:
    /* data */
public:
    Math(/* args */) = default;
    ~Math() = default;

public:
    static void InitRandomSeed()
    {
        static bool seeded = false;
        if (!seeded)
        {
            srand(static_cast<unsigned int>(time(nullptr)));
            seeded = true;
        }
    }

    // 1. 获取X轴方向（0：目标在左侧，1：目标在右侧）
    static int getDirectionToTargetX(float objX, float x)
    {
        return (objX > x) ? 0 : 1;
    }

    // 2. 生成[Min, Max]范围内的随机整数（左闭右闭）
    static int Rand(int Min, int Max)
    {
        InitRandomSeed(); // 确保随机数种子已初始化
        if (Min > Max)
        {
            throw std::invalid_argument("Rand: Min must be less than or equal to Max");
        }
        // 计算随机数范围：(Max - Min + 1)个可能值
        int range = Max - Min + 1;
        // rand()返回[0, RAND_MAX]，通过取模和偏移实现范围映射
        return Min + (rand() % range);
    }

    // 3. 从数组中随机获取一个元素（支持任意可索引容器）
    template <typename T>
    static T GetRandomElementFromArray(const std::vector<T> &arr)
    {
        if (arr.empty())
        {
            throw std::invalid_argument("GetRandomElementFromArray: Array is empty");
        }
        int randomIndex = Rand(0, static_cast<int>(arr.size()) - 1);
        return arr[randomIndex];
    }

    // 5. 根据方向计算偏移后的X坐标
    static float GetDistancePos(float startX, int direction, float offsetX)
    {
        return (direction == 0) ? (startX - offsetX) : (startX + offsetX);
    }

    // 6. 通过两点坐标计算旋转角度（预留实现，需根据具体需求补充）
    static float getRorateAngleByCurrentPos(float x1, float y1, float z1, float x2, float y2, float z2)
    {
        // 示例实现：计算X-Z平面内的角度（可根据需求调整为3D角度）
        float dx = x2 - x1;
        float dz = z2 - z1;
        // atan2(dz, dx)：返回与X轴正方向的夹角（弧度），范围[-π, π]
        return std::atan2(dz, dx);
    }

    // 8. 标准抛物线计算（y = a(x - c/2)² + b，开口向下）
    static float sq_Parabola(float x, float b, float c)
    {
        if (c == 0)
        {
            throw std::invalid_argument("sq_Parabola: c cannot be zero");
        }
        // 计算抛物线系数a（确保顶点在x=c/2，y=b）
        float a = (-4.0f * b) / (c * c);
        return a * (x - c / 2.0f) * (x - c / 2.0f) + b;
    }

    // 9. 计算2D平面两点距离（Y轴权重0.29，用于透视校正）
    static float Get2D_Distance(float x1, float y1, float x2, float y2)
    {
        float offsetX = x1 - x2;
        float offsetY = (y1 - y2) * 0.29f;
        // 勾股定理计算距离
        return std::sqrt(offsetX * offsetX + offsetY * offsetY);
    }

    // 10. 判断角度是否在[startA, endA]形成的锐角范围内（角度单位：度）
    static bool CheckAngleIsInArea(float judge, float startA, float endA)
    {
        // 步骤1：将角度标准化到[0, 360)范围
        auto normalizeAngle = [](float angle)
        {
            angle = std::fmod(angle, 360.0f);
            return (angle < 0) ? (angle + 360.0f) : angle;
        };

        startA = normalizeAngle(startA);
        endA = normalizeAngle(endA);
        judge = normalizeAngle(judge);

        // 特殊情况：范围跨0度（如startA=350°，endA=10°）
        if (startA > 270.0f && startA < 360.0f && endA > 0.0f && endA < 90.0f)
        {
            return (judge >= startA && judge <= 360.0f) || (judge >= 0.0f && judge <= endA);
        }
        // 普通情况：范围不跨0度
        else
        {
            // 处理startA > endA的正常范围（如startA=30°，endA=60°）
            if (startA > endA)
            {
                std::swap(startA, endA);
            }
            return (judge >= startA && judge <= endA);
        }
    }

    // 11. 弧度转角度
    static float toDegree(float radian)
    {
        return radian * 57.2957795f; // 180/π ≈ 57.2957795
    }

    // 12. 角度转弧度
    static float toRadian(float degree)
    {
        return degree * 0.0174532925f; // π/180 ≈ 0.0174532925
    }

    // 13. 判断点是否在立方体内（立方体由对角点定义）
    static bool pointIsInCubeArea(float px, float py, float pz,
                                  float startX, float startY, float startZ,
                                  float endX, float endY, float endZ)
    {
        // 计算立方体中心点和半边长
        float cubeCenterX = (startX + endX) / 2.0f;
        float cubeXLen = std::fabs(startX - endX) / 2.0f;

        float cubeCenterY = (startY + endY) / 2.0f;
        float cubeYLen = std::fabs(startY - endY) / 2.0f;

        float cubeCenterZ = (startZ + endZ) / 2.0f;
        float cubeZLen = std::fabs(startZ - endZ) / 2.0f;

        // 点到各轴中心点的距离 ≤ 半边长 → 在立方体内
        return (std::fabs(px - cubeCenterX) <= cubeXLen + 1e-6f) &&
               (std::fabs(py - cubeCenterY) <= cubeYLen + 1e-6f) &&
               (std::fabs(pz - cubeCenterZ) <= cubeZLen + 1e-6f);
    }

    // 14. 立方体与立方体碰撞检测（基于顶点和中心点判断）
    static bool CubeAndCubeCollection(float c1StartX, float c1StartY, float c1StartZ,
                                      float c1EndX, float c1EndY, float c1EndZ,
                                      float c2StartX, float c2StartY, float c2StartZ,
                                      float c2EndX, float c2EndY, float c2EndZ)
    {
        // 优化说明：原Squirrel代码判断过多冗余点，此处保留核心顶点+中心点判断
        const std::vector<std::tuple<float, float, float>> c1Points = {
            // 立方体1的8个顶点
            {c1StartX, c1StartY, c1StartZ},
            {c1EndX, c1StartY, c1StartZ},
            {c1StartX, c1EndY, c1StartZ},
            {c1EndX, c1EndY, c1StartZ},
            {c1StartX, c1StartY, c1EndZ},
            {c1EndX, c1StartY, c1EndZ},
            {c1StartX, c1EndY, c1EndZ},
            {c1EndX, c1EndY, c1EndZ},
            // 立方体1的中心点
            {(c1StartX + c1EndX) / 2, (c1StartY + c1EndY) / 2, (c1StartZ + c1EndZ) / 2}};

        const std::vector<std::tuple<float, float, float>> c2Points = {
            // 立方体2的8个顶点
            {c2StartX, c2StartY, c2StartZ},
            {c2EndX, c2StartY, c2StartZ},
            {c2StartX, c2EndY, c2StartZ},
            {c2EndX, c2EndY, c2StartZ},
            {c2StartX, c2StartY, c2EndZ},
            {c2EndX, c2StartY, c2EndZ},
            {c2StartX, c2EndY, c2EndZ},
            {c2EndX, c2EndY, c2EndZ},
            // 立方体2的中心点
            {(c2StartX + c2EndX) / 2, (c2StartY + c2EndY) / 2, (c2StartZ + c2EndZ) / 2}};

        // 检查立方体1的点是否在立方体2内
        for (const auto &[x, y, z] : c1Points)
        {
            if (pointIsInCubeArea(x, y, z, c2StartX, c2StartY, c2StartZ, c2EndX, c2EndY, c2EndZ))
            {
                return true;
            }
        }

        // 检查立方体2的点是否在立方体1内
        for (const auto &[x, y, z] : c2Points)
        {
            if (pointIsInCubeArea(x, y, z, c1StartX, c1StartY, c1StartZ, c1EndX, c1EndY, c1EndZ))
            {
                return true;
            }
        }

        return false;
    }

    // 15. 计算三角形面积（叉乘法，避免开方，效率更高）
    static float get3PointArea(float x1, float y1, float x2, float y2, float x3, float y3)
    {
        // 面积公式：0.5 * |x1(y2-y3) + x2(y3-y1) + x3(y1-y2)|
        return 0.5f * std::fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
    }

    // 16. 计算四边形面积（拆分为两个三角形面积之和）
    static float get4PointArea(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
    {
        // 四边形拆分为：(x1,y1)-(x2,y2)-(x3,y3) 和 (x2,y2)-(x3,y3)-(x4,y4)
        float area1 = get3PointArea(x1, y1, x2, y2, x3, y3);
        float area2 = get3PointArea(x2, y2, x3, y3, x4, y4);
        return area1 + area2;
    }

    // 17. 判断点是否在四边形内（面积比较法，要求四边形顶点按顺序排列）
    static bool pointIsIn4PointArea(float px, float py,
                                    float x1, float y1, float x2, float y2,
                                    float x3, float y3, float x4, float y4)
    {
        const float eps = 10.0f; // 容差（原Squirrel代码定义为10.0）
        float totalArea = get4PointArea(x1, y1, x2, y2, x3, y3, x4, y4);
        // 点与四边形各边组成的4个三角形面积之和
        float sumArea = get3PointArea(x1, y1, x2, y2, px, py) +
                        get3PointArea(x2, y2, x3, y3, px, py) +
                        get3PointArea(x3, y3, x4, y4, px, py) +
                        get3PointArea(x4, y4, x1, y1, px, py);

        // 面积差在容差范围内 → 点在四边形内
        return std::fabs(totalArea - sumArea) < eps;
    }

    // 18. 判断点是否在矩形内（矩形由坐标数组定义，格式：[x, y, width, height]）
    static bool PointIsInSquare(float x1, float y1, const std::vector<float> &SquareArr)
    {
        if (SquareArr.size() != 4)
        {
            throw std::invalid_argument("PointIsInSquare: SquareArr must have 4 elements (x, y, width, height)");
        }
        float sqX = SquareArr[0];
        float sqY = SquareArr[1];
        float sqWidth = SquareArr[2];
        float sqHeight = SquareArr[3];

        // 点的X在[sqX, sqX+width]，Y在[sqY, sqY+height] → 在矩形内
        return (x1 >= sqX - 1e-6f) && (x1 <= sqX + sqWidth + 1e-6f) &&
               (y1 >= sqY - 1e-6f) && (y1 <= sqY + sqHeight + 1e-6f);
    }

    static float getUniformVelocity(float sv, float ev, float currentRate, float maxRate)
    {
        // 避免除零错误
        if (maxRate <= 0.0f)
        {
            throw std::invalid_argument("maxRate must be greater than 0");
        }

        // 计算当前进度比例（0.0到1.0之间）
        float rate = currentRate / maxRate;
        // 限制比例在[0, 1]范围内，避免超出边界
        rate = std::clamp(rate, 0.0f, 1.0f);

        // 计算变化量并返回当前值
        float varyValue = ev - sv;
        return sv + varyValue * rate;
    }
};