from src.builder.text_file_maze_builder import TextFileMazeBuilder
from src.strategy.bfs_strategy import BFSStrategy
from src.strategy.dfs_strategy import DFSStrategy
from src.strategy.astar_strategy import AStarStrategy
from src.solver.maze_solver import MazeSolver
from src.ui.console_view import ConsoleView
from src.ui.player import Player
from src.ui.move_command import MoveCommand


def choose_maze():
    mazes = {
        "1": ("small.txt",  "Small  — маленький лабиринт"),
        "2": ("medium.txt", "Medium — средний лабиринт"),
        "3": ("big.txt",    "Big    — большой лабиринт(тупиковый)"),
        "4": ("empty.txt",  "Empty  — пустой лабиринт"),
        "5": ("no_exit.txt","NoExit — без выхода")
    }

    print("\n" + "═" * 40)
    print("        ВЫБОР ЛАБИРИНТА")
    print("═" * 40)

    for key, (_, desc) in mazes.items():
        print(f" {key}. {desc}")

    print("═" * 40)

    choice = input("Введите номер: ").strip()

    if choice not in mazes:
        print("Неверный выбор, загружаю small.txt")
        return "small.txt"

    filename = mazes[choice][0]
    print(f"Загружен: {filename}")
    return filename


def main():
    builder = TextFileMazeBuilder()

    filename = choose_maze()
    maze = builder.build_from_file(f"../mazes/{filename}")

    view = ConsoleView()
    view.update(f"Maze '{filename}' loaded")

    strategies = {
        "bfs": BFSStrategy(),
        "dfs": DFSStrategy(),
        "astar": AStarStrategy()
    }

    print("\nВыберите алгоритм:")
    print("  bfs   — поиск в ширину")
    print("  dfs   — поиск в глубину")
    print("  astar — A*")
    algo = input("Введите название: ").strip().lower()

    strategy = strategies.get(algo, BFSStrategy())

    solver = MazeSolver(maze, strategy)
    stats = solver.solve()
    print(stats)

    # визуализация пути
    path, visited = strategy.find_path(maze, maze.start, maze.exit)
    view.render(maze, None, path)

    # пошаговый режим
    player = Player(maze.start)

    while True:
        cmd = input("Ход (w/a/s/d) или q для выхода: ").strip().lower()
        if cmd == "q":
            break

        dxdy = {
            "w": (0, -1),
            "s": (0, 1),
            "a": (-1, 0),
            "d": (1, 0)
        }

        if cmd not in dxdy:
            continue

        dx, dy = dxdy[cmd]
        new_cell = maze.get_cell(player.current_cell.x + dx,
                                 player.current_cell.y + dy)

        if not new_cell or not new_cell.is_passable():
            print("Там стена, туда нельзя.")
            continue

        move = MoveCommand(player, new_cell)
        move.execute()
        view.render(maze, player.current_cell, path)


if __name__ == "__main__":
    main()
