use bone_types::{Length, Parameter, Point2, Point3};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct ClosestPoint<P> {
    parameter: Parameter,
    point: P,
    distance: Length,
}

pub type ClosestPoint2 = ClosestPoint<Point2>;
pub type ClosestPoint3 = ClosestPoint<Point3>;

impl<P: Copy> ClosestPoint<P> {
    #[must_use]
    pub const fn new(parameter: Parameter, point: P, distance: Length) -> Self {
        Self {
            parameter,
            point,
            distance,
        }
    }

    #[must_use]
    pub const fn parameter(self) -> Parameter {
        self.parameter
    }

    #[must_use]
    pub const fn point(self) -> P {
        self.point
    }

    #[must_use]
    pub const fn distance(self) -> Length {
        self.distance
    }
}

impl<P: core::fmt::Display> core::fmt::Display for ClosestPoint<P> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        use uom::si::length::millimeter;
        write!(
            f,
            "closest{{ t={}, p={}, d={} mm }}",
            self.parameter.value(),
            self.point,
            self.distance.get::<millimeter>(),
        )
    }
}
