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

use crate::gradient::*;
use crate::mesh::*;
use crate::mesh_2d::index_2d::*;
use crate::mesh_source::*;

pub fn repr_mesh_with_gradient_2d(mesh: &(impl Mesh + Index2D), gradient: &Gradient) -> String {
    let mut output = String::new();
    let (width, height) = mesh.shape();
    for y in 0..height {
        for x in 0..width {
            let c = match mesh.xy_to_index(x, y) {
                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');
    }
    output
}

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

    #[test]
    fn test_repr_distance_full_rectangle() {
        let rect = Full2D::new(8, 6);
        let mut grad = Gradient::from_mesh(&rect);
        let repr1 = repr_mesh_with_gradient_2d(&rect, &grad);
        assert_eq!(
            "????????\n????????\n????????\n????????\n????????\n????????\n",
            repr1.as_str()
        );
        grad.set_distance(18, 0.0);
        let repr2 = repr_mesh_with_gradient_2d(&rect, &grad);
        assert_eq!(
            "????????\n????????\n??0?????\n????????\n????????\n????????\n",
            repr2.as_str()
        );
        grad.spread_forward(&rect, 0.0);
        let repr3 = repr_mesh_with_gradient_2d(&rect, &grad);
        assert_eq!(
            "????????\n?1112345\n31012345\n21112345\n32223456\n43334456\n",
            repr3.as_str()
        );
        grad.spread(&rect);
        let repr4 = repr_mesh_with_gradient_2d(&rect, &grad);
        assert_eq!(
            "32223456\n21112345\n21012345\n21112345\n32223456\n43334456\n",
            repr4.as_str()
        );
    }
}
