use crate::core::filter::CreateFilterSampler;
use shared::Float;
use shared::core::filter::FilterSampler;
use shared::core::geometry::{Point2f, Vector2f};
use shared::filters::LanczosSincFilter;
use shared::utils::math::windowed_sinc;

pub trait LanczosFilterCreator {
    fn new(radius: Vector2f, tau: Float) -> Self;
}

impl LanczosFilterCreator for LanczosSincFilter {
    fn new(radius: Vector2f, tau: Float) -> Self {
        let sampler = FilterSampler::new(radius, move |p: Point2f| {
            windowed_sinc(p.x(), radius.x(), tau) * windowed_sinc(p.y(), radius.y(), tau)
        });

        let sqrt_samples = 64;
        let n_samples = sqrt_samples * sqrt_samples;
        let area = (2.0 * self.radius.x()) * (2.0 * self.radius.y());
        let mut sum = 0.0;
        let mut rng = rand::rng();

        for y in 0..sqrt_samples {
            for x in 0..sqrt_samples {
                let u = Point2f::new(
                    (x as Float + rng.random::<Float>()) / sqrt_samples as Float,
                    (y as Float + rng.random::<Float>()) / sqrt_samples as Float,
                );
                let p = Point2f::new(
                    lerp(u.x(), -self.radius.x(), self.radius.x()),
                    lerp(u.y(), -self.radius.y(), self.radius.y()),
                );
                sum += self.evaluate(p);
            }
        }
        let integral = sum / n_samples as Float * area;

        Self {
            radius,
            tau,
            sampler,
            integral,
        }
    }
}
