//! throwaway_proj — an aura research project: node logic + the exported vocabulary.
//!
//! Every node type this crate provides is registered in `vocabulary()` /
//! `type_ids()` under the `throwaway_proj::` namespace prefix; the `aura` host loads
//! this cdylib per invocation and merges it with the std vocabulary.

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

/// One-input scalar gain: emits `input * factor`. Emits `None` until its
/// input has a value (warm-up filter, C8).
pub struct Scale {
    factor: f64,
    out: [Cell; 1],
}

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

impl Node for Scale {
    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] * self.factor);
        Some(&self.out)
    }
    fn label(&self) -> String {
        format!("throwaway_proj::Scale({})", self.factor)
    }
}

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

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

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