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

use shortestpath::mesh_2d::Compact2D;

use crate::{GameHandler, Place2D, World};

/// Width of the default battlefield (80 columns)
pub const BATTLEFIELD_WIDTH: usize = 80;

/// Height of the default battlefield (50 rows)
pub const BATTLEFIELD_HEIGHT: usize = 50;

/// Returns the hardcoded maze map as a string.
/// The maze is 80 columns * 50 rows
/// '#' represents walls, ' ' represents walkable areas.
/// Features narrow corridors and several larger open rooms.
pub fn default_maze() -> &'static str {
    concat!(
        "################################################################################\n",
        "#            #       #                                              ########   #\n",
        "#   #   #    #   #   #                                                         #\n",
        "#   #   #    #   #   ############# ###                                         #\n",
        "#   #   #        #                   #                                         #\n",
        "#   #   #   ######   #######   #######                                         #\n",
        "#   #   #        #   #     #   #                                               #\n",
        "#   #   ######   #   #     #   #                   ############                #\n",
        "#   #        #   #   #     #   #                   #          #                #\n",
        "#   ######   #   #         #   #                   #          #                #\n",
        "#        #   #   #   #######   #                   #   ####   #                #\n",
        "#        #   #   #             #                   #   #  #   #                #\n",
        "######   #   #   #   ###########                   #   #  #   #                #\n",
        "#        #       #   #                             #   #  #   #                #\n",
        "#   ######  ######   #                             #   #      #                #\n",
        "#                    #                             #   ########                #\n",
        "#   ##########   #####                                                         #\n",
        "#            #                                                                 #\n",
        "#            #   ############################                                  #\n",
        "#   ######   #   #                          #                                  #\n",
        "#   #    #   #   #                          #                                  #\n",
        "#   #    #   #   #   ####################   #                                  #\n",
        "#   #    #   #   #   #                  #   #                                  #\n",
        "#   #    #       #   #                  #   #                                  #\n",
        "#   #    #       #   #   ############   #   #                                  #\n",
        "#   #    #  ######   #   #          #   #   #                                  #\n",
        "#   #    #       #   #   #          #   #   #                                  #\n",
        "#   #    ######  #   #   #   ####   #   #   #                                  #\n",
        "#   #         #  #   #   #   #  #   #   #   #                                  #\n",
        "#   #######   #  #           #  #   #   #                                      #\n",
        "#         #   #  #   #   #   #  #   #   ###################                    #\n",
        "#         #   #  #   #   #   #  #   #        #                                 #\n",
        "#   ####  #   #  #   #   ########   ######   #                                 #\n",
        "#      #  #      #   #                   #   #                                 #\n",
        "#      #  ########   ###############     #   #                                 #\n",
        "#      #                                 #   #                                 #\n",
        "#      #                                 #   #                                 #\n",
        "#      #   #########################     #   #                                 #\n",
        "#      #   #                             #                                     #\n",
        "#      #   #   #########################                                       #\n",
        "#      #   #   #                                                               #\n",
        "#          #   #   #######################                                     #\n",
        "#   ########   #   #                     #                                     #\n",
        "#              #   #                     #                                     #\n",
        "#   ############   #   #################                                      ##\n",
        "#                  #   #               #                                       #\n",
        "#                  #   #               #                                       #\n",
        "#   ################   #               #                                       #\n",
        "#                      #                                                       #\n",
        "################################################################################\n"
    )
}

/// Creates a default simulation with the hardcoded maze.
///
/// Returns a GameHandler wrapping a 2D world with a battlefield of 80x50 cells.
/// The maze contains narrow corridors and several larger open rooms
/// suitable for gameplay.
pub fn create_default_simulation(
) -> Result<GameHandler<World<Compact2D, Place2D>>, shortestpath::Error> {
    let mesh = Compact2D::from_text(default_maze())?.unique();
    let world = World::new_2d(mesh)?;
    Ok(GameHandler::new(world))
}

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

    #[test]
    fn test_maze_dimensions() {
        let maze = default_maze();
        let lines: Vec<&str> = maze.lines().collect();

        assert_eq!(lines.len(), BATTLEFIELD_HEIGHT, "Maze should have 50 rows");

        for (i, line) in lines.iter().enumerate() {
            assert_eq!(
                line.len(),
                BATTLEFIELD_WIDTH,
                "Row {} should have 80 columns, got {}",
                i,
                line.len()
            );
        }
    }

    #[test]
    fn test_create_default_simulation() {
        let handler = create_default_simulation().expect("Failed to create default simulation");
        let world = handler.state();

        // The mesh should have walkable cells (less than total because of walls)
        assert!(world.place_count() > 0, "World should have walkable places");
        assert!(
            world.place_count() < BATTLEFIELD_WIDTH * BATTLEFIELD_HEIGHT,
            "World should have fewer places than total cells due to walls"
        );
    }

    #[test]
    fn test_maze_has_border_walls() {
        let maze = default_maze();
        let lines: Vec<&str> = maze.lines().collect();

        // First and last rows should be all walls
        assert!(
            lines[0].chars().all(|c| c == '#'),
            "First row should be all walls"
        );
        assert!(
            lines[BATTLEFIELD_HEIGHT - 1].chars().all(|c| c == '#'),
            "Last row should be all walls"
        );

        // First and last columns should be walls
        for (i, line) in lines.iter().enumerate() {
            let chars: Vec<char> = line.chars().collect();
            assert_eq!(chars[0], '#', "First column at row {} should be wall", i);
            assert_eq!(
                chars[BATTLEFIELD_WIDTH - 1],
                '#',
                "Last column at row {} should be wall",
                i
            );
        }
    }
}
