use super::mesh::LodLevel;

pub struct LodConfig {
    pub radius: f64,
    pub low_poly_distance: f64,
    pub medium_poly_distance: f64,
}

impl LodConfig {
    pub fn new(radius: f64) -> Self {
        Self {
            radius,
            low_poly_distance: radius * 500.0,
            medium_poly_distance: radius * 100.0,
        }
    }

    pub fn with_distances(radius: f64, medium: f64, low: f64) -> Self {
        Self {
            radius,
            low_poly_distance: low,
            medium_poly_distance: medium,
        }
    }

    pub fn select_lod(&self, camera_distance: f64) -> LodLevel {
        if camera_distance > self.low_poly_distance {
            LodLevel::Low
        } else if camera_distance > self.medium_poly_distance {
            LodLevel::Medium
        } else {
            LodLevel::High
        }
    }

    pub fn angular_diameter_rad(&self, camera_distance: f64) -> f64 {
        2.0 * (self.radius / camera_distance).atan()
    }

    pub fn pixel_diameter(&self, camera_distance: f64, fov_rad: f64, viewport_height: u32) -> f64 {
        let angular = self.angular_diameter_rad(camera_distance);
        (angular / fov_rad) * viewport_height as f64
    }

    pub fn adaptive_subdivisions(
        &self,
        camera_distance: f64,
        fov_rad: f64,
        viewport_height: u32,
    ) -> u32 {
        let pixels = self.pixel_diameter(camera_distance, fov_rad, viewport_height);
        if pixels < 16.0 {
            1
        } else if pixels < 64.0 {
            2
        } else if pixels < 256.0 {
            3
        } else if pixels < 1024.0 {
            4
        } else if pixels < 4096.0 {
            5
        } else {
            6
        }
    }
}
