use crate::Float;
use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::sample_tent;
use num_traits::Float as NumFloat;

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

impl TriangleFilter {
    pub fn new(radius: Vector2f) -> Self {
        Self { radius }
    }
}

impl FilterTrait for TriangleFilter {
    fn radius(&self) -> Vector2f {
        self.radius
    }

    fn evaluate(&self, p: Point2f) -> Float {
        (self.radius.x() - p.x().abs()).max(0.0) * (self.radius.y() - p.y().abs()).max(0.0)
    }

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

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