use crate::Float;
use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::lerp;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct BoxFilter {
    pub radius: Vector2f,
}

impl BoxFilter {
    pub fn new(radius: Vector2f) -> Self {
        Self { radius }
    }
}
impl FilterTrait for BoxFilter {
    fn radius(&self) -> Vector2f {
        self.radius
    }

    fn evaluate(&self, p: Point2f) -> Float {
        if p.x().abs() <= self.radius.x() && p.y().abs() <= self.radius.y() {
            1.
        } else {
            0.
        }
    }

    fn integral(&self) -> Float {
        (2.0 * self.radius.x()) * (2.0 * self.radius.y())
    }

    fn sample(&self, u: Point2f) -> FilterSample {
        let p = Point2f::new(
            lerp(u[0], -self.radius.x(), self.radius.x()),
            lerp(u[1], -self.radius.y(), self.radius.y()),
        );
        FilterSample { p, weight: 1.0 }
    }
}
