//! Fixture node crate for the #241 [nodes] pointer e2e: lives one level
//! BELOW its Aura.toml (`../Aura.toml` points at this dir via
//! `[nodes].crates`), unlike the demo-project fixture which collocates the
//! crate at the project root. One pass-through node under the `ptr`
//! namespace, exported via the descriptor macro.

use aura_core::{
    Cell, Ctx, FieldSpec, Firing, Node, NodeSchema, PortSpec, PrimitiveBuilder,
    ScalarKind,
};

/// One-input f64 pass-through. Emits `None` until its input has a value.
pub struct Identity {
    out: [Cell; 1],
}

impl Identity {
    pub fn new() -> Self {
        Self { out: [Cell::from_f64(0.0)] }
    }
    pub fn builder() -> PrimitiveBuilder {
        PrimitiveBuilder::new(
            "ptr::Identity",
            NodeSchema {
                inputs: vec![PortSpec {
                    kind: ScalarKind::F64,
                    firing: Firing::Any,
                    name: "value".into(),
                }],
                output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
                params: vec![],
            },
            |_| Box::new(Identity::new()),
        )
    }
}

impl Default for Identity {
    fn default() -> Self {
        Self::new()
    }
}

impl Node for Identity {
    fn lookbacks(&self) -> Vec<usize> {
        vec![1]
    }
    fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Cell]> {
        let w = ctx.f64_in(0);
        if w.is_empty() {
            return None;
        }
        self.out[0] = Cell::from_f64(w[0]);
        Some(&self.out)
    }
    fn label(&self) -> String {
        "ptr::Identity".to_string()
    }
}

fn vocabulary(type_id: &str) -> Option<PrimitiveBuilder> {
    match type_id {
        "ptr::Identity" => Some(Identity::builder()),
        _ => None,
    }
}

fn type_ids() -> &'static [&'static str] {
    &["ptr::Identity"]
}

aura_core::aura_project! {
    namespace: "ptr",
    vocabulary: vocabulary,
    type_ids: type_ids,
}
