#!/usr/bin/env python
# coding: utf-8

# In[7]:


import sys
import os

# Добавляем текущую папку в путь
sys.path.insert(0, os.getcwd())

# Импорты с вашими именами файлов
from modelsMaze import Maze, Cell
from buildersText_maze_builder import TextFieldMazeBuilder
from strategiesBfs_strategy import BFSStrategy
from strategiesDfs_strategy import DFSStrategy
from strategiesA_star_strategy import AStarStrategy
from solverMaze_solver import MazeSolver
from visualizationConsole_view import ConsoleView
from commandsPlayer import Player
from commandsMove_command import MoveCommand
from experimentsBenchmark import Benchmark

def create_test_mazes():
    """Создать тестовые лабиринты в папке mazes/."""
    mazes_dir = "mazes"
    os.makedirs(mazes_dir, exist_ok=True)

    # Маленький лабиринт 10×10
    small = [
        "##########",
        "#S       #",
        "# #####  #",
        "# #   #  #",
        "# # # #  #",
        "#   # #  #",
        "##### #  #",
        "#       #",
        "#      E#",
        "##########",
    ]

    # Пустой лабиринт
    empty = ["S" + " " * 48 + "E"] + [" " * 50 for _ in range(48)]

    # Лабиринт без выхода
    no_exit = [
        "##########",
        "#S       #",
        "# #####  #",
        "# #   #  #",
        "# # # #  #",
        "#   # #  #",
        "##### #  #",
        "#        #",
        "##########",
        "##########",
    ]

    mazes = {
        "small.txt": small,
        "empty.txt": empty,
        "no_exit.txt": no_exit,
    }

    for name, content in mazes.items():
        path = os.path.join(mazes_dir, name)
        with open(path, 'w', encoding='utf-8') as f:
            f.write('\n'.join(content))
        print(f"Создан тестовый лабиринт: {path}")

    print()

def demo_builder_and_strategy():
    """Демонстрация паттернов Builder и Strategy."""
    print("\n" + "=" * 60)
    print("ДЕМОНСТРАЦИЯ ПАТТЕРНОВ BUILDER И STRATEGY")
    print("=" * 60)

    builder = TextFieldMazeBuilder()
    maze = builder.build_from_file("mazes/small.txt")

    strategies = [
        BFSStrategy(),
        DFSStrategy(),
        AStarStrategy(),
    ]

    for strategy in strategies:
        print(f"\n--- Используем стратегию: {strategy.name} ---")
        solver = MazeSolver(maze, strategy)
        path = solver.solve()

        if path:
            print(f"  Путь найден! Длина: {len(path)}")
            print(f"  Время: {solver.last_stats.time_ms:.2f} мс")
            print(f"  Посещено клеток: {solver.last_stats.visited_cells}")
        else:
            print("  Путь не найден!")

    return maze

def demo_observer(maze: Maze):
    """Демонстрация паттерна Observer."""
    print("\n" + "=" * 60)
    print("ДЕМОНСТРАЦИЯ ПАТТЕРНА OBSERVER")
    print("=" * 60)

    view = ConsoleView(maze)
    solver = MazeSolver(maze, BFSStrategy())
    solver.attach(view)

    print("Запускаем поиск с наблюдателем...")
    path = solver.solve()

    view.set_solution_path(path)
    view.render()

    return view

def demo_command(maze: Maze, view: ConsoleView):
    """Демонстрация паттерна Command."""
    print("\n" + "=" * 60)
    print("ДЕМОНСТРАЦИЯ ПАТТЕРНА COMMAND")
    print("=" * 60)

    player = Player(maze, maze.start_cell)
    view.set_player_position(player.position)

    print("Управление игроком:")
    print("  W/A/S/D - движение, Z - отмена, Q - выход")

    history = []

    while True:
        view.render()

        cmd = input("Ваш ход: ").strip().lower()

        if cmd == 'q':
            break
        elif cmd == 'z':
            if history:
                last_cmd = history.pop()
                last_cmd.undo()
                view.set_player_position(player.position)
                print("Последний ход отменён")
            else:
                print("Нечего отменять")
        elif cmd in MoveCommand.DIRECTIONS:
            move_cmd = MoveCommand(player, maze, cmd)
            if move_cmd.execute():
                history.append(move_cmd)
                view.set_player_position(player.position)

                if player.position == maze.exit_cell:
                    print("\n🎉 ПОБЕДА! ВЫ НАШЛИ ВЫХОД! 🎉")
                    view.render()
                    break
            else:
                print("Туда нельзя пройти")
        else:
            print("Неизвестная команда")

    print("Игра завершена")

def run_experiments():
    """Запуск экспериментального сравнения."""
    print("\n" + "=" * 60)
    print("ЭКСПЕРИМЕНТАЛЬНОЕ СРАВНЕНИЕ АЛГОРИТМОВ")
    print("=" * 60)

    builder = TextFieldMazeBuilder()
    benchmark = Benchmark()

    maze_files = ["small.txt", "empty.txt", "no_exit.txt"]

    for maze_file in maze_files:
        try:
            maze = builder.build_from_file(f"mazes/{maze_file}")
            print(f"\nТестируем: {maze_file} ({maze.width}×{maze.height})")
            benchmark.run_on_maze(maze, maze_file, iterations=5)
        except FileNotFoundError:
            print(f"Файл {maze_file} не найден")
        except ValueError as e:
            print(f"Ошибка: {e}")

    benchmark.print_summary()
    benchmark.save_to_csv()

def main():
    """Главная функция."""
    print("=" * 60)
    print("ПРОГРАММА ПОИСКА ВЫХОДА ИЗ ЛАБИРИНТА")
    print("Паттерны: Builder, Strategy, Observer, Command")
    print("=" * 60)

    create_test_mazes()
    maze = demo_builder_and_strategy()
    view = demo_observer(maze)
    demo_command(maze, view)
    run_experiments()

    print("\nПрограмма завершена!")

if __name__ == "__main__":
    main()


# In[ ]:




