use crate::physics::orbit::MERCURY_RADIUS;

#[derive(Debug, Clone, Copy)]
pub struct Vertex {
    pub position: [f64; 3],
    pub normal: [f64; 3],
    pub uv: [f32; 2],
    pub tangent: [f64; 3],
}

pub struct TerrainMesh {
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u32>,
}

impl TerrainMesh {
    pub fn from_region(
        lat_min: f64,
        lat_max: f64,
        lon_min: f64,
        lon_max: f64,
        subdivisions: u32,
    ) -> Self {
        let mut vertices = Vec::new();
        let mut indices = Vec::new();
        let rows = subdivisions + 1;
        let cols = subdivisions + 1;

        for j in 0..rows {
            for i in 0..cols {
                let u = i as f64 / subdivisions as f64;
                let v = j as f64 / subdivisions as f64;
                let lat = lat_min + v * (lat_max - lat_min);
                let lon = lon_min + u * (lon_max - lon_min);
                let lat_rad = lat.to_radians();
                let lon_rad = lon.to_radians();
                let r = MERCURY_RADIUS;

                let x = r * lat_rad.cos() * lon_rad.cos();
                let y = r * lat_rad.cos() * lon_rad.sin();
                let z = r * lat_rad.sin();

                let len = (x * x + y * y + z * z).sqrt();
                let nx = x / len;
                let ny = y / len;
                let nz = z / len;

                let tx = -lon_rad.sin();
                let ty = lon_rad.cos();
                let tz = 0.0;

                vertices.push(Vertex {
                    position: [x, y, z],
                    normal: [nx, ny, nz],
                    uv: [u as f32, v as f32],
                    tangent: [tx, ty, tz],
                });
            }
        }

        for j in 0..subdivisions {
            for i in 0..subdivisions {
                let a = j * cols + i;
                let b = a + 1;
                let c = a + cols;
                let d = c + 1;
                indices.push(a);
                indices.push(c);
                indices.push(b);
                indices.push(b);
                indices.push(c);
                indices.push(d);
            }
        }

        Self { vertices, indices }
    }

    pub fn vertex_count(&self) -> usize {
        self.vertices.len()
    }

    pub fn triangle_count(&self) -> usize {
        self.indices.len() / 3
    }
}

pub fn vertex_count(lod: u8) -> usize {
    match lod {
        5 => 65536,
        4 => 16384,
        3 => 4096,
        2 => 1024,
        _ => 256,
    }
}

pub fn base_radius() -> f64 {
    MERCURY_RADIUS
}
