// Port of de.varylab.discreteconformal.uniformization.SurfaceCurveUtilityTest
// (Java/JUnit) — the two pure-math tests that don't need the HDS.

#include "projective_math.hpp"

#include <gtest/gtest.h>
#include <Eigen/Dense>

using Eigen::VectorXd;
using conformallab::isOnSegment;
using conformallab::getPointOnCorrespondingSegment;
using conformallab::dehomogenize;

// Helper: make VectorXd from initializer list.
static VectorXd V(std::initializer_list<double> vals) {
    VectorXd v(vals.size());
    int i = 0;
    for (double x : vals) v(i++) = x;
    return v;
}

// A point exactly at the midpoint of segment lies on it; a slightly perturbed
// point perpendicular to the segment does not.
TEST(SurfaceCurveUtilityTest, IsOnSegment) {
    VectorXd x1 = V({1, 1, 1, 1});
    VectorXd x2 = V({1 + 1e-5, 1, 1, 1});
    VectorXd s0 = V({0, 0, 0, 1});
    VectorXd s1 = V({2, 2, 2, 1});

    EXPECT_TRUE(isOnSegment(x1, s0, s1));
    EXPECT_FALSE(isOnSegment(x2, s0, s1));
}

// The edge point coincides (within floating-point) with the END of the edge
// segment, so the corresponding point on the target segment must be its end.
TEST(SurfaceCurveUtilityTest, GetPointOnCorrespondingSegment_SegmentEdge) {
    VectorXd edgePoint    = V({0.352392439203295, 0.9123804930829212, 1.0});
    VectorXd edgeSrc0     = V({0.34745306897719913, 0.912568467121888, 1.0});
    VectorXd edgeSrc1     = V({0.35239243920431296, 0.912380493082885, 1.0});
    VectorXd tgt0         = V({-0.2896352574166635,  0.03146361746587523,
                                0.10643898885661185,  0.44373020886051084});
    VectorXd tgt1         = V({-0.2666822290964323,  0.019034256494171405,
                                0.10525293907970201,  0.44373020886051084});

    VectorXd result = getPointOnCorrespondingSegment(
        edgePoint, edgeSrc0, edgeSrc1, tgt0, tgt1);

    // Expected: dehomogenized tgt1 (edgePoint is at the end of the source segment).
    VectorXd expected = dehomogenize(tgt1);

    ASSERT_EQ(expected.size(), result.size());
    for (int i = 0; i < result.size(); i++) {
        EXPECT_NEAR(expected(i), result(i), 1e-9) << "component " << i;
    }
}
