#pragma once
// conformal_mesh.hpp
//
// Central mesh type for the discrete conformal mapping algorithms.
// Replaces the Java CoHDS (de.varylab.discreteconformal.heds.CoHDS)
// and its associated vertex/edge/face types (CoVertex, CoEdge, CoFace).
//
// Design
// ------
//   Java                         │  C++ (this file)
//   ─────────────────────────────┼──────────────────────────────────────────
//   CoHDS                        │  ConformalMesh   (CGAL::Surface_mesh)
//   CoVertex / CoEdge / CoFace   │  Vertex_index / Edge_index / Face_index
//   HyperIdealRadiusAdapter      │  property_map<Vertex_index, double>
//   HalfedgeInterface adapters   │  named property maps ("v:lambda", …)
//
// Property-map naming convention
// ───────────────────────────────
//   "v:lambda"    per-vertex log scale factor  (conformal variable u_i)
//   "v:theta"     per-vertex target cone angle
//   "v:idx"       per-vertex solver DOF index  (-1 = pinned / boundary)
//   "e:alpha"     per-edge intersection angle  (α_ij, hyperbolic geometry)
//   "f:type"      per-face geometry type       (0=Euclidean, 1=Hyperbolic, 2=Spherical)
//
// All property maps are optional; add only what a given algorithm needs.
//
// Note on descriptor types (CGAL 6.x)
// ────────────────────────────────────
// CGAL::Surface_mesh exposes its index types as nested types:
//   Surface_mesh::Vertex_index, ::Halfedge_index, ::Edge_index, ::Face_index
// The BGL graph_traits aliases expose the same types as vertex_descriptor etc.,
// but those live in boost::graph_traits<Surface_mesh>, not in Surface_mesh itself.
// We use the Surface_mesh member names throughout for clarity.

#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <string>

namespace conformallab {

// ── Kernel ──────────────────────────────────────────────────────────────────
// Simple double-precision Cartesian.  Conformal mapping algorithms never
// need exact arithmetic — they operate on floating-point lengths and angles.
using Kernel = CGAL::Simple_cartesian<double>;
using Point3 = Kernel::Point_3;
using Point2 = Kernel::Point_2;

// ── Mesh type ────────────────────────────────────────────────────────────────
using ConformalMesh = CGAL::Surface_mesh<Point3>;

// ── Index/descriptor aliases (CGAL 6.x naming) ───────────────────────────────
using Vertex_index   = ConformalMesh::Vertex_index;
using Halfedge_index = ConformalMesh::Halfedge_index;
using Edge_index     = ConformalMesh::Edge_index;
using Face_index     = ConformalMesh::Face_index;

// ── Geometry type constant (replaces Java CoFace.type enum) ─────────────────
enum class GeometryType : int {
    Euclidean  = 0,
    Hyperbolic = 1,
    Spherical  = 2
};

// ── Standard property-map bundles ────────────────────────────────────────────

// Add the vertex properties used by all conformal-map functionals.
// Returns {lambda, theta, idx}.
inline auto add_vertex_properties(ConformalMesh& mesh)
{
    auto [lambda, ok1] = mesh.add_property_map<Vertex_index, double>("v:lambda", 0.0);
    auto [theta,  ok2] = mesh.add_property_map<Vertex_index, double>("v:theta",  0.0);
    auto [idx,    ok3] = mesh.add_property_map<Vertex_index, int>   ("v:idx",   -1);
    (void)ok1; (void)ok2; (void)ok3;
    return std::make_tuple(lambda, theta, idx);
}

// Add the edge intersection-angle property used by the hyperbolic functional.
inline auto add_edge_properties(ConformalMesh& mesh)
{
    auto [alpha, ok] = mesh.add_property_map<Edge_index, double>("e:alpha", 0.0);
    (void)ok;
    return alpha;
}

// Add the face geometry-type property.
inline auto add_face_properties(ConformalMesh& mesh)
{
    auto [ftype, ok] = mesh.add_property_map<Face_index, int>(
        "f:type", static_cast<int>(GeometryType::Euclidean));
    (void)ok;
    return ftype;
}

} // namespace conformallab
