// Copyright (C) 2025 Christian Mauduit <ufoot@ufoot.org>

//! Cell type definitions for pathfinding meshes.
//!
//! This module defines the basic cell types used throughout the library
//! to represent walkable and non-walkable cells.

/// Represents the type of a cell in a pathfinding mesh.
///
/// Cells can be floors (walkable) or walls (obstacles).
///
/// # Example
///
/// ```
/// use shortestpath::mesh_source::CellType;
///
/// let cell = CellType::FLOOR;
/// assert!(cell.can_go());
///
/// let wall = CellType::WALL;
/// assert!(!wall.can_go());
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CellType {
    /// A floor (walkable) cell that agents can move through.
    FLOOR,
    /// A wall (obstacle) cell that blocks movement.
    WALL,
}

impl CellType {
    /// Returns `true` if agents can move through this cell.
    ///
    /// This is the primary method for checking if a cell is traversable.
    /// Currently returns `true` for `FLOOR` cells and `false` for `WALL` cells.
    /// Future cell types (like directional cells) may have more complex logic.
    ///
    /// # Example
    ///
    /// ```
    /// use shortestpath::mesh_source::CellType;
    ///
    /// assert!(CellType::FLOOR.can_go());
    /// assert!(!CellType::WALL.can_go());
    /// ```
    #[inline]
    pub fn can_go(&self) -> bool {
        matches!(self, CellType::FLOOR)
    }
}

impl From<bool> for CellType {
    /// Converts a boolean to a CellType.
    ///
    /// `true` maps to `WALL`, `false` maps to `FLOOR`.
    ///
    /// # Example
    ///
    /// ```
    /// use shortestpath::mesh_source::CellType;
    ///
    /// assert_eq!(CellType::from(false), CellType::FLOOR);
    /// assert_eq!(CellType::from(true), CellType::WALL);
    /// ```
    fn from(is_wall: bool) -> Self {
        if is_wall {
            CellType::WALL
        } else {
            CellType::FLOOR
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[cfg(feature = "serde")]
    fn test_serde() {
        let floor = CellType::FLOOR;
        let wall = CellType::WALL;

        let floor_json = serde_json::to_string(&floor).unwrap();
        let wall_json = serde_json::to_string(&wall).unwrap();

        let floor_deserialized: CellType = serde_json::from_str(&floor_json).unwrap();
        let wall_deserialized: CellType = serde_json::from_str(&wall_json).unwrap();

        assert_eq!(floor, floor_deserialized);
        assert_eq!(wall, wall_deserialized);
    }
}
