// neuron.sy — A Hodgkin-Huxley neuron in Scyla
// The first temporal program ever written in Scyla
// Aislinn McCubbins, April 2, 2026

temporal struct Neuron {
    state voltage: Float = -65.0,
    state gate_m: Float = 0.05,
    state gate_h: Float = 0.6,
    state gate_n: Float = 0.32,
    const g_na: Float = 120.0,
    const g_k: Float = 36.0,
    const g_leak: Float = 0.3,
    const e_na: Float = 50.0,
    const e_k: Float = -77.0,
    const e_leak: Float = -54.387,
}

impl Evolve for Neuron {
    fn evolve(&mut self, dt: Duration) {
        // Alpha/beta rate constants — NOT sigmoid
        let am = 0.1 * (self.voltage + 40.0) / (1.0 - exp(-(self.voltage + 40.0) / 10.0))
        let bm = 4.0 * exp(-(self.voltage + 65.0) / 18.0)
        let ah = 0.07 * exp(-(self.voltage + 65.0) / 20.0)
        let bh = 1.0 / (1.0 + exp(-(self.voltage + 35.0) / 10.0))
        let an = 0.01 * (self.voltage + 55.0) / (1.0 - exp(-(self.voltage + 55.0) / 10.0))
        let bn = 0.125 * exp(-(self.voltage + 65.0) / 80.0)

        // Steady states
        let m_inf = am / (am + bm)
        let h_inf = ah / (ah + bh)
        let n_inf = an / (an + bn)

        // Gate dynamics: dm/dt = (m_inf - m) / tau
        let tau_m = 1.0 / (am + bm)
        let tau_h = 1.0 / (ah + bh)
        let tau_n = 1.0 / (an + bn)

        self.gate_m += (m_inf - self.gate_m) / tau_m * dt.seconds()
        self.gate_h += (h_inf - self.gate_h) / tau_h * dt.seconds()
        self.gate_n += (n_inf - self.gate_n) / tau_n * dt.seconds()

        // Ionic currents
        let i_na = self.g_na * (self.gate_m ** 3) * self.gate_h * (self.voltage - self.e_na)
        let i_k = self.g_k * (self.gate_n ** 4) * (self.voltage - self.e_k)
        let i_leak = self.g_leak * (self.voltage - self.e_leak)

        // Membrane equation
        self.voltage += (-i_na - i_k - i_leak) * dt.seconds()
    }
}

impl Neuron {
    fn stimulate(&mut self, current: Float) {
        // Presence modulates, doesn't compute
        self.voltage += current * 0.01
    }

    fn spiked(&self) -> Bool {
        self.voltage > 0.0
    }
}

fn main() {
    let mut neuron = Neuron {}

    // Stimulate and observe
    neuron.stimulate(15.0)

    let traj = neuron.run(duration: 10.ms)

    for state in traj.observe(every: 0.1.ms) {
        println("t={state.time:.1}ms  V={state.voltage:.1}mV  m={state.gate_m:.3}  h={state.gate_h:.3}")
    }

    if neuron.spiked() {
        println("The neuron fired!")
    }
}
