/*
    Appellation: drivers <module>
    Contrib: @FL03
*/
//! this module works to provide various _drivers_ (a.k.a. plants) for each of the partitions
//! (virtual nodes) within the substrate.
#[doc(inline)]
pub use self::plant::Plant;

mod plant;

pub(crate) mod prelude {
    pub use super::plant::Plant;
    pub use super::{Driver, RawDriver, TriadDriver};
    pub use super::{NeuralPlant, WolframPlant};
}

use crate::engine::RawEngine;
use crate::nrt::{LPR, Triad};

/// A type alias for a plant with a neural engine
pub type NeuralPlant<T = f32> = Plant<crate::engine::NeuralEngine<T>>;
/// A type alias for a plant with a Wolfram [2, 3] UTM engine
pub type WolframPlant<Q = usize, S = usize> = Plant<crate::engine::WolframUTM<Q, S>>;

/// The raw driver trait defines the common interface for all plants. Drivers are fundamental
/// to the operation of the framework as they equip virtualized entities with various
/// abilities, such as computability.
pub trait RawDriver<C>: Send + Sync + core::fmt::Debug {
    type Engine: RawEngine;

    fn engine(&self) -> &Self::Engine;

    fn engine_mut(&mut self) -> &mut Self::Engine;

    fn headspace(&self) -> &C;

    fn headspace_mut(&mut self) -> &mut C;

    private!();
}

/// The driver trait extends the raw driver trait by adding the ability to clone and
/// synchronize the driver. This is useful for creating multiple instances of the same
/// driver and for sharing the driver across threads.
///
/// The driver trait also provides various creation routines based on known parameters.
pub trait Driver<H>: RawDriver<H>
where
    Self: Clone + Default,
{
    /// create a new driver with the given headspace
    fn from_headspace(headspace: H) -> Self;
}

/// specific methods for [`triad`](Triad)-based drivers
pub trait TriadDriver: Driver<Triad> {
    fn transform(&mut self, transform: LPR) -> Result<(), crate::ActorError>;

    fn walk<'a, I>(&mut self, iter: I) -> Result<(), crate::ActorError>
    where
        I: IntoIterator<Item = &'a LPR>;
}
