#ifndef GJK_INTERFACE_HPP
#define GJK_INTERFACE_HPP

#include <vector>
#include <Eigen/Dense>

typedef enum {
    COLLISION_RESULT_NO_COLLISION = 0,
    COLLISION_RESULT_COLLISION = 1,
    COLLISION_RESULT_ERROR = -1
} CollisionResultE;

struct OBB {
    Eigen::Vector3d center;       // 中心
    Eigen::Vector3d axis[3];      // 3条正交的棱边方向轴（单位向量）
    double halfExtent[3];  // 沿各轴的半长（从中心到面的距离）
    double selfMinProject[3];
    double selfMaxProject[3];
    double maxRadius;

    OBB() {
        center = Eigen::Vector3d::Zero();
        for (int i = 0; i < 3; ++i) {
            axis[i] = Eigen::Vector3d::Zero();
            halfExtent[i] = 0.0;
            selfMinProject[i] = 0.0;
            selfMaxProject[i] = 0.0;
        }
    }
};

typedef enum {
    AXIS_DISTANCE_LONG = 0,
    AXIS_OBB_A_AXIS_0 = 1,
    AXIS_OBB_A_AXIS_1 = 2,
    AXIS_OBB_A_AXIS_2 = 3,
    AXIS_OBB_B_AXIS_0 = 4,
    AXIS_OBB_B_AXIS_1 = 5,
    AXIS_OBB_B_AXIS_2 = 6,
    AXIS_A0_CROSS_B0 = 7,
    AXIS_A0_CROSS_B1 = 8,
    AXIS_A0_CROSS_B2 = 9,
    AXIS_A1_CROSS_B0 = 10,
    AXIS_A1_CROSS_B1 = 11,
    AXIS_A1_CROSS_B2 = 12,
    AXIS_A2_CROSS_B0 = 13,
    AXIS_A2_CROSS_B1 = 14,
    AXIS_A2_CROSS_B2 = 15,
    AXIS_CNT = 16,
} AxisE;

struct AxisStats {
    int64_t hitCount[AXIS_CNT];
    int axisRank[AXIS_CNT];
    AxisStats() {
        for (int i = 0; i < AXIS_CNT; ++i) {
            hitCount[i] = 0;
            axisRank[i] = i;
        }
    }
};

namespace gjk_interface {
    bool gjkCollisionJudge(const std::vector<Eigen::Vector3d>& polyA, const std::vector<Eigen::Vector3d>& polyB);
    OBB createOBBFromVertices(const std::vector<Eigen::Vector3d>& vertices,
        const float length, const float width, const float height);
    OBB createOBBFromPoints(const std::vector<Eigen::Vector3d>& vertices);
    OBB updateOBBFromPoints(OBB originalOBB, Eigen::Vector3d translation, Eigen::Quaterniond rotation);
    bool checkOBBCollision(const OBB &obb1, const OBB &obb2);
    bool checkOBBCollisionNew(const OBB &A, const OBB &B, AxisStats *stats);
    bool checkOBBCollisionNewTemp(const OBB &A, const OBB &B, AxisStats *stats);
    // Optimized SAT-based OBB-OBB collision (no axis normalization, scalar math)
    bool checkOBBCollision2(const OBB &a, const OBB &b);
    void getSelfProject(OBB &self);

    void GetAxisLog(double &checkAxisAve);
    void BubbleSortAxisByHitCount(AxisStats *stats);
} // namespace gjk_interface

#endif // GJK_INTERFACE_HPP