//! A minimal recording sink a downstream consumer would author (C8 sink role,
//! C22: displayable = exactly what a sink recorded).
//!
//! It declares a single `f64` input with `Firing::Any`, an empty `output`
//! (the pure-consumer declaration), and in `eval` pushes `(now, value)` to a
//! destination it holds as a field — an out-of-graph side effect. Returns
//! `None` (records nothing into the graph).

use std::cell::RefCell;
use std::rc::Rc;

use aura_core::{Ctx, Firing, InputSpec, Node, NodeSchema, Scalar, ScalarKind, Timestamp};

/// Shared, out-of-graph destination the recorder writes into.
pub type Tape = Rc<RefCell<Vec<(Timestamp, f64)>>>;

pub struct Recorder {
    tape: Tape,
}

impl Recorder {
    pub fn new(tape: Tape) -> Self {
        Self { tape }
    }
}

impl Node for Recorder {
    fn schema(&self) -> NodeSchema {
        NodeSchema {
            inputs: vec![InputSpec {
                kind: ScalarKind::F64,
                lookback: 1,
                firing: Firing::Any,
            }],
            output: vec![], // pure consumer (sink)
        }
    }

    fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Scalar]> {
        if let Some(v) = ctx.f64_in(0).get(0) {
            self.tape.borrow_mut().push((ctx.now(), v));
        }
        None
    }
}
