/*!
Abstract traits for manifolds.
*/

use serde::Serialize;
use alg_tools::euclidean::Euclidean;

/// A point on a manifold
pub trait ManifoldPoint : Clone + PartialEq {
    // Type of tangent factors
    type Tangent : Euclidean<f64, Output=Self::Tangent> + std::fmt::Debug + Serialize;

    /// Exponential map
    fn exp(self, tangent : &Self::Tangent) -> Self;

    /// Logarithmic map
    fn log(&self, other : &Self) -> Self::Tangent;

    /// Distance to `other`
    fn dist_to(&self, other : &Self) -> f64;

    /// Return the zero tangent at `self`.
    fn tangent_origin(&self) -> Self::Tangent;
}

/// Point on a manifold that possesses displayable embedded coordinates.
pub trait EmbeddedManifoldPoint : ManifoldPoint + std::fmt::Debug {
    type EmbeddedCoords : std::fmt::Display + Serialize;

    /// Convert a point on a manifold into embedded coordinates
    fn embedded_coords(&self) -> Self::EmbeddedCoords;
}

/// Point on a manifold that possesses faces
pub trait FacedManifoldPoint : ManifoldPoint + std::fmt::Debug {
    type Face : std::fmt::Display + Serialize;

    /// Convert a point on a manifold into embedded coordinates
    fn face(&self) -> Self::Face;
}
