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

use crate::errors::*;
use crate::mesh_topo::topology::*;

/// A simple boolean topology that enables or disables all connections.
///
/// `TopologyBool` is the simplest topology implementation, controlled by a single
/// boolean flag. When `true`, all connections are allowed; when `false`, all
/// connections are blocked.
///
/// This is useful for scenarios like:
/// - Global lockdown (disable all movement)
/// - Region-wide door systems (all doors open/closed together)
/// - Toggle between accessible/inaccessible states
///
/// # Example
///
/// ```
/// use shortestpath::mesh_topo::{Topology, TopologyBool};
///
/// let mut topology = TopologyBool::new(true);
/// assert_eq!(topology.allowed(0, 1).unwrap(), true);
///
/// // Disable all connections
/// topology.set(false);
/// assert_eq!(topology.allowed(0, 1).unwrap(), false);
///
/// // Re-enable
/// topology.set(true);
/// assert_eq!(topology.allowed(0, 1).unwrap(), true);
/// ```
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TopologyBool {
    /// The current status: true = all connections allowed, false = all blocked
    status: bool,
}

impl TopologyBool {
    /// Creates a new boolean topology with the specified initial state.
    ///
    /// # Arguments
    ///
    /// * `status` - Initial state: `true` to allow all connections, `false` to block all
    ///
    /// # Example
    ///
    /// ```
    /// use shortestpath::mesh_topo::TopologyBool;
    ///
    /// let topology = TopologyBool::new(true); // All connections allowed
    /// ```
    pub fn new(status: bool) -> Self {
        TopologyBool { status }
    }

    /// Sets the topology state.
    ///
    /// # Arguments
    ///
    /// * `status` - New state: `true` to allow all connections, `false` to block all
    ///
    /// # Example
    ///
    /// ```
    /// use shortestpath::mesh_topo::TopologyBool;
    ///
    /// let mut topology = TopologyBool::new(true);
    /// topology.set(false); // Block all connections
    /// ```
    pub fn set(&mut self, status: bool) {
        self.status = status
    }

    /// Gets the current topology state.
    ///
    /// # Returns
    ///
    /// The current state: `true` if connections are allowed, `false` if blocked
    ///
    /// # Example
    ///
    /// ```
    /// use shortestpath::mesh_topo::TopologyBool;
    ///
    /// let topology = TopologyBool::new(true);
    /// assert_eq!(topology.get(), true);
    /// ```
    pub fn get(&self) -> bool {
        self.status
    }
}

impl Topology for TopologyBool {
    fn allowed(&self, _from: usize, _to: usize) -> Result<bool> {
        Ok(self.status)
    }
}

impl From<bool> for TopologyBool {
    fn from(status: bool) -> TopologyBool {
        TopologyBool::new(status)
    }
}

impl From<TopologyBool> for bool {
    fn from(topo: TopologyBool) -> bool {
        topo.get()
    }
}

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

    #[test]
    #[cfg(feature = "serde")]
    fn test_serde() {
        let topology = TopologyBool::new(true);
        let json = serde_json::to_string(&topology).unwrap();
        let deserialized: TopologyBool = serde_json::from_str(&json).unwrap();

        assert_eq!(topology.get(), deserialized.get());
    }
}
