//! Node status types for behavior execution
//!
//! This module defines the possible states a behavior node can be in during execution.

use serde::{Deserialize, Serialize};
use std::fmt;

/// Status returned by behavior nodes after each tick.
///
/// This follows the standard behavior tree status model with three states.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum NodeStatus {
    /// The behavior completed successfully.
    ///
    /// For example:
    /// - A movement command reached its goal
    /// - An object was successfully detected
    /// - A message was successfully sent
    Success,

    /// The behavior failed and cannot recover.
    ///
    /// For example:
    /// - An object was not found after extensive searching
    /// - A connection could not be established
    /// - A safety constraint was violated
    ///
    /// Note: Use this for logical failures, not exceptions.
    /// Throw errors for exceptional conditions.
    Failure,

    /// The behavior is still executing and needs more ticks.
    ///
    /// For example:
    /// - A robot is still moving to a goal
    /// - Waiting for a sensor reading
    /// - Processing a long-running computation
    #[default]
    Running,
}

impl NodeStatus {
    /// Returns true if the status indicates completion (Success or Failure).
    ///
    /// # Example
    ///
    /// ```rust
    /// use mecha10_behavior_runtime::NodeStatus;
    ///
    /// assert!(NodeStatus::Success.is_complete());
    /// assert!(NodeStatus::Failure.is_complete());
    /// assert!(!NodeStatus::Running.is_complete());
    /// ```
    pub fn is_complete(&self) -> bool {
        matches!(self, NodeStatus::Success | NodeStatus::Failure)
    }

    /// Returns true if the status is Success.
    pub fn is_success(&self) -> bool {
        matches!(self, NodeStatus::Success)
    }

    /// Returns true if the status is Failure.
    pub fn is_failure(&self) -> bool {
        matches!(self, NodeStatus::Failure)
    }

    /// Returns true if the status is Running.
    pub fn is_running(&self) -> bool {
        matches!(self, NodeStatus::Running)
    }
}

impl fmt::Display for NodeStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            NodeStatus::Success => write!(f, "Success"),
            NodeStatus::Failure => write!(f, "Failure"),
            NodeStatus::Running => write!(f, "Running"),
        }
    }
}
