use dyntri_core::triangulation::simplices::CausalSimplex2Kind;
use serde::{Deserialize, Serialize};

/// Enum representing the orientation of a `Triangle`
///
/// `Up` meaning that the point of the `Triangle` points in positive time direction;
/// `Down` meaning that the point of the `Triangle` points in negative time direction.
#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Orientation {
    Down = 0,
    Up = 1,
}

/// Struct representing a `Triangle`, containing it's `orientation` and connectivity.
///
/// Connectivity is given by `left`, being a `Label` to the left neighbour of the `Triangle`;
/// `center`, being a `Label` to the timelike neighbour of the `Triangle`; and `right`, being
/// a `Label` to the right neighbour of the `Triangle`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Triangle {
    // Labels are meant to refer to other triangles in a LabelledList
    /// Left neighbour in the thick timeslice
    pub left: usize,
    /// Timelike neighbour in either previous or next thick timeslice for orientations
    /// `Up` or `Down` respectively.
    pub center: usize,
    /// Right neigbour in the thick timeslice
    pub right: usize,
    /// Orientation of the triangle, point pointing `Up` or `Down`
    pub orientation: Orientation,
}

impl From<Orientation> for CausalSimplex2Kind {
    fn from(value: Orientation) -> Self {
        match value {
            Orientation::Down => CausalSimplex2Kind::S12,
            Orientation::Up => CausalSimplex2Kind::S21,
        }
    }
}

#[cfg(test)]
pub mod display {
    use super::*;
    use std::fmt::Display;

    impl Orientation {
        /// Returns a character representing the `Orientation`
        pub fn char(&self) -> char {
            match self {
                Orientation::Up => '▲',
                Orientation::Down => '▼',
            }
        }
    }

    impl Display for Orientation {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(f, "{}", self.char())
        }
    }
}
