// Finite impulse response filters

use std::collections::VecDeque;

use crate::{complex::Complex32, filtering::impulse_response};

pub struct FIRFilter {
    size: usize,
    normalization: f32,
    impulse_response: Box<[Complex32]>,
    taps: VecDeque<Complex32>,
}

impl FIRFilter {
    pub fn new(impulse_response: &[Complex32]) -> Self {
        FIRFilter {
            size: impulse_response.len(),
            impulse_response: impulse_response.iter().copied().collect(),
            /*
            normalization: impulse_response
                .iter()
                .map(|x| x.mag())
                .reduce(|acc, e| acc.max(e))
                .unwrap(),
            */
            normalization: 1., // DC normalization
            // TODO: Maybe we'd want other types of normalization (per frequency)
            taps: VecDeque::from(vec![Complex32::zero(); impulse_response.len()]),
        }
    }

    pub fn normalize_sum(&mut self)
    {
        self.normalization = self.impulse_response.iter().copied().sum::<Complex32>().mag()
    }

    pub fn next(&mut self, next: Complex32) -> Complex32 {
        let _ = self.taps.pop_front();

        self.taps.push_back(next);
        self.taps
            .iter()
            .zip(self.impulse_response.iter())
            .map(|(tap, coef)| *tap * *coef)
            .sum::<Complex32>()
            / self.normalization
    }

    pub fn next_real(&mut self, next: f32) -> f32 {
        self.next(Complex32::new(next, 0.)).re
    }
}
