use std::{
    fmt::{Debug, Display},
    sync::{Arc, Mutex},
};

/// Lambda function that can be called by a Mustache template with no arguments.
#[derive(Clone)]
pub struct Provider(pub Arc<Mutex<dyn FnMut() -> String + Send>>);

impl Provider {
    /// Create a new [`Provider`] from a closure.
    pub fn new(fun: impl FnMut() -> String + Send + 'static) -> Self {
        Self(Arc::new(Mutex::new(fun)))
    }
}

impl Debug for Provider {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Debug::fmt("<λ () -> String>", f)
    }
}
impl Display for Provider {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "<λ () -> String>")
    }
}

/// Lambda function that can be called by a Mustache template; transforming the section contents.
#[derive(Clone)]
pub struct Transformer(pub Arc<Mutex<dyn FnMut(&str) -> String + Send>>);

impl Transformer {
    /// Create a new [`Transformer`] from a closure.
    pub fn new(fun: impl FnMut(&str) -> String + Send + 'static) -> Self {
        Self(Arc::new(Mutex::new(fun)))
    }
}

impl Debug for Transformer {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Debug::fmt("<λ String -> String>", f)
    }
}
impl Display for Transformer {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "<λ String -> String>")
    }
}
