// Copyright (C) 2025 Christian Mauduit <ufoot@ufoot.org>

use crate::gradient::*;
use crate::mesh::*;
use crate::mesh_3d::index_3d::*;
use crate::mesh_source::*;

pub fn repr_mesh_with_gradient_3d(mesh: &(impl Mesh + Index3D), gradient: &Gradient) -> String {
    let mut output = String::new();
    let (width, height, depth) = mesh.shape();
    for z in 0..depth {
        for y in 0..height {
            for x in 0..width {
                let c = match mesh.xyz_to_index(x, y, z) {
                    Ok(index) => {
                        let distance = gradient.get_distance(index);
                        if distance >= i32::MAX as f64 || distance <= i32::MIN as f64 {
                            '?'
                        } else {
                            let mut modulo = (distance.round() as i32) % 10;
                            if modulo < 0 {
                                modulo += 10;
                            }
                            let base0: u32 = '0' as u32;
                            char::from_u32(base0 + (modulo as u32)).unwrap_or('E')
                        }
                    }
                    Err(_) => Source2DFromText::DEFAULT_WALL_CHAR,
                };
                output.push(c);
            }
            output.push('\n');
        }
        for _ in 0..width {
            output.push(Source2DFromText::DEFAULT_SEP_CHAR);
        }
        output.push('\n');
    }
    output
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::mesh_3d::full_3d::*;

    #[test]
    fn test_repr_distance_full_rectangle() {
        let rect = Full3D::new(5, 4, 3);
        let mut grad = Gradient::from_mesh(&rect);
        let repr1 = repr_mesh_with_gradient_3d(&rect, &grad);
        assert_eq!(
	    "?????\n?????\n?????\n?????\n-----\n?????\n?????\n?????\n?????\n-----\n?????\n?????\n?????\n?????\n-----\n",
            repr1.as_str()
        );
        grad.set_distance(18, 0.0);
        let repr2 = repr_mesh_with_gradient_3d(&rect, &grad);
        assert_eq!(
	    "?????\n?????\n?????\n???0?\n-----\n?????\n?????\n?????\n?????\n-----\n?????\n?????\n?????\n?????\n-----\n",
            repr2.as_str()
        );
        grad.spread_forward(&rect, 0.0);
        let repr3 = repr_mesh_with_gradient_3d(&rect, &grad);
        assert_eq!(
	    "?????\n?????\n??111\n?3101\n-----\n?????\n?3323\n53212\n42111\n-----\n54444\n43333\n43323\n43222\n-----\n",
            repr3.as_str()
        );
        grad.spread(&rect);
        let repr4 = repr_mesh_with_gradient_3d(&rect, &grad);
        assert_eq!(
	    "44333\n43222\n32111\n32101\n-----\n54434\n43323\n43212\n32111\n-----\n54444\n43333\n43323\n43222\n-----\n",
            repr4.as_str()
        );
    }
}
