// Copyright (c) 2024-2026 Tarik Moussa.
// SPDX-License-Identifier: MIT
//
// Package: conformallab++ / Discrete_conformal_map (Phase 8 MVP, 2026-05-19)

/*!
\file CGAL/Conformal_map_traits.h
\ingroup PkgConformalMapRef

Defines the `ConformalMapTraits` concept and the default model
`Default_conformal_map_traits<TriangleMesh, K>` for the package.

The concept lists the types and property maps that the discrete-conformal
algorithms require from any backing data structure.  By templatising the
algorithms on this concept, the package can run on any CGAL halfedge
mesh — `Surface_mesh`, `Polyhedron_3`, OpenMesh-adapter, pmp — without
changes to the algorithm code.

For Phase 8 MVP only the `Surface_mesh` specialisation is provided
(specialisation 8a.1).  A generic `FaceGraph` specialisation is on the
roadmap as 8a.2.

\sa `CGAL::Discrete_conformal_map`
\sa `CGAL::parameters::vertex_curvature_map`
*/

#ifndef CGAL_CONFORMAL_MAP_TRAITS_H
#define CGAL_CONFORMAL_MAP_TRAITS_H

#include <CGAL/Surface_mesh.h>
#include <CGAL/Simple_cartesian.h>
#include <boost/graph/graph_traits.hpp>

namespace CGAL {

// ════════════════════════════════════════════════════════════════════════════
// \cgalConcept
//
// \concept ConformalMapTraits
// \ingroup PkgConformalMapConcepts
//
// The concept `ConformalMapTraits` describes the requirements that any
// Traits model must fulfil for the Discrete_conformal_map package.
//
// \cgalHasModelsBegin
// \cgalHasModels{CGAL::Default_conformal_map_traits<TriangleMesh, K>}
// \cgalHasModelsEnd
//
// \section RequiredTypes Required types
//
// | Type | Description |
// |------|-------------|
// | `Triangle_mesh` | A model of CGAL `FaceGraph` + `HalfedgeGraph`. |
// | `Kernel`        | A CGAL kernel; defaults to `Simple_cartesian<double>`. |
// | `FT`            | Field type used internally (typically `double`). |
// | `Vertex_descriptor`   | `boost::graph_traits<Triangle_mesh>::vertex_descriptor`. |
// | `Halfedge_descriptor` | analogously. |
// | `Edge_descriptor`     | analogously. |
// | `Face_descriptor`     | analogously. |
//
// \section RequiredProperties Required property-map accessors
//
// The Traits class is responsible for *locating* the property maps that
// the algorithm reads from and writes to.  The semantics follow the
// project conventions (see `doc/api/contracts.md` for the full table):
//
// | Property             | Key                     | Value | Access  | Used by |
// |----------------------|-------------------------|-------|---------|---------|
// | `vertex_points(m)`   | `Vertex_descriptor`     | `Point_3` | Read | input geometry |
// | `theta_map(m)`       | `Vertex_descriptor`     | `FT`  | RW      | target cone angle Θᵥ |
// | `vertex_index_map(m)`| `Vertex_descriptor`     | `int` | RW      | DOF index (−1 = pinned) |
// | `lambda0_map(m)`     | `Edge_descriptor`       | `FT`  | RW      | base log-length λ°ᵢⱼ |
//
// Each accessor is a `static` member that returns the map; it must be
// idempotent (calling twice yields the same map by name lookup).
// ════════════════════════════════════════════════════════════════════════════


// ════════════════════════════════════════════════════════════════════════════
// Default_conformal_map_traits  —  primary template (undefined)
// ════════════════════════════════════════════════════════════════════════════
//
// The undefined primary template forces specialisation per mesh type.
// MVP provides only the `Surface_mesh` specialisation below; further
// mesh types (Polyhedron_3, OpenMesh, pmp) are deferred to Phase 8a.2.

template <typename TriangleMesh,
          typename Kernel_ = CGAL::Simple_cartesian<double>>
struct Default_conformal_map_traits;


// ════════════════════════════════════════════════════════════════════════════
// Specialisation: CGAL::Surface_mesh<K::Point_3>
// ════════════════════════════════════════════════════════════════════════════

/*!
\ingroup PkgConformalMapRef

Default traits for `CGAL::Surface_mesh`.  Wraps the property maps that
the existing implementation (`code/include/euclidean_functional.hpp`)
attaches to a Surface_mesh under the `"ev:idx"`, `"ev:theta"`,
`"ee:lam0"` etc. names.

This specialisation is the only one available in Phase 8 MVP.  It is
selected automatically when `TriangleMesh = CGAL::Surface_mesh<...>`.

\tparam K  Any CGAL kernel.  Defaults to `Simple_cartesian<double>`,
           which is what `conformal_mesh.hpp` uses today.
*/
template <typename K>
struct Default_conformal_map_traits<CGAL::Surface_mesh<typename K::Point_3>, K>
{
    using Kernel        = K;
    using FT            = typename K::FT;
    using Point_3       = typename K::Point_3;
    using Triangle_mesh = CGAL::Surface_mesh<Point_3>;

    using Vertex_descriptor   = typename boost::graph_traits<Triangle_mesh>::vertex_descriptor;
    using Halfedge_descriptor = typename boost::graph_traits<Triangle_mesh>::halfedge_descriptor;
    using Edge_descriptor     = typename boost::graph_traits<Triangle_mesh>::edge_descriptor;
    using Face_descriptor     = typename boost::graph_traits<Triangle_mesh>::face_descriptor;

    // Property-map types — match the names used by setup_euclidean_maps().
    using Vertex_point_map      = typename Triangle_mesh::template Property_map<Vertex_descriptor, Point_3>;
    using Theta_pmap            = typename Triangle_mesh::template Property_map<Vertex_descriptor, FT>;
    using Vertex_index_pmap     = typename Triangle_mesh::template Property_map<Vertex_descriptor, int>;
    using Lambda0_pmap          = typename Triangle_mesh::template Property_map<Edge_descriptor, FT>;

    // ─── Property-map accessors ───────────────────────────────────────────
    //
    // Each accessor returns a property map under its canonical legacy name.
    // If no such map exists yet it is created with sensible defaults — so
    // calling either `setup_euclidean_maps(m)` first or the accessor first
    // is equivalent.

    static Vertex_point_map vertex_points(Triangle_mesh& m) {
        return m.points();
    }

    static Theta_pmap theta_map(Triangle_mesh& m) {
        auto [pm, created] = m.template add_property_map<Vertex_descriptor, FT>(
            "ev:theta", FT(2.0 * 3.141592653589793238));
        (void)created;
        return pm;
    }

    static Vertex_index_pmap vertex_index_map(Triangle_mesh& m) {
        auto [pm, created] = m.template add_property_map<Vertex_descriptor, int>(
            "ev:idx", -1);
        (void)created;
        return pm;
    }

    static Lambda0_pmap lambda0_map(Triangle_mesh& m) {
        auto [pm, created] = m.template add_property_map<Edge_descriptor, FT>(
            "ee:lam0", FT(0));
        (void)created;
        return pm;
    }
};

}  // namespace CGAL

#endif  // CGAL_CONFORMAL_MAP_TRAITS_H
