#include <catch2/catch_test_macros.hpp>
#include <fmt/core.h>
#include <string>
#include "matrix.hpp"
#include "rand.hpp"
#include "constants.hpp"
#include "maze.hpp"

using std::string;
using matrix::Matrix;

TEST_CASE("hunt-and-kill", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.hunt_and_kill();
  // maze.dump("BASIC MAZE");

  maze.randomize_rooms();
  maze.hunt_and_kill();

  REQUIRE(map.$dead_ends.size() > 0);
  REQUIRE(map.$rooms.size() > 0);

  for(auto& room : maze.$rooms) {
    for(matrix::box it{maze.$walls, room.x, room.y, room.width};
        it.next();)
    {
      maze.$walls[it.y][it.x] = WALL_PATH_LIMIT;
    }
  }
}

TEST_CASE("hunt-and-kill box", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.inner_box(5, 3);
  maze.hunt_and_kill();

  for(auto at : maze.$dead_ends) {
    maze.$walls[at.y][at.x]=32;
  }
  // maze.dump("INNER BOX");

  REQUIRE(maze.$rooms.size() == 0);
}

TEST_CASE("hunt-and-kill ring", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.inner_donut(5.5, 3.5);
  maze.hunt_and_kill();

  for(auto at : maze.$dead_ends) {
    maze.$walls[at.y][at.x]=32;
  }
  // maze.dump("INNER RING");

  REQUIRE(maze.$rooms.size() == 0);
}

TEST_CASE("hunt-and-kill fissure", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.divide({3,3}, {19,18});
  maze.hunt_and_kill();

  for(auto at : maze.$dead_ends) {
    maze.$walls[at.y][at.x]=32;
  }
  // maze.dump("FISSURE MAZE");

  REQUIRE(maze.$rooms.size() == 0);
}



TEST_CASE("hunt-and-kill no-dead-ends", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.hunt_and_kill();

  maze.remove_dead_ends();

  // maze.dump("NO DEAD ENDS");
}

TEST_CASE("hunt-and-kill too much", "[mazes]") {
  Map map(21, 21);
  maze::Builder maze(map);

  maze.hunt_and_kill();
  maze.randomize_rooms();
  maze.init();
  maze.inner_donut(4, 2);
  maze.divide({3,3}, {19,18});
  maze.hunt_and_kill();

  // maze.dump("COMBINED");
}