#!/usr/bin/env python3
"""
Test Dijkstra Pathfinding Implementation
========================================

Demonstrates:
1. Computing Dijkstra distance map from a root position
2. Getting distances to any position
3. Finding paths from any position back to the root
4. Multi-target pathfinding (flee/approach scenarios)
"""

import mcrfpy
from mcrfpy import libtcod
import sys

def create_test_grid():
    """Create a test grid with obstacles"""
    mcrfpy.createScene("dijkstra_test")
    
    # Create grid
    grid = mcrfpy.Grid(grid_x=20, grid_y=20)
    
    # Initialize all cells as walkable
    for y in range(grid.grid_y):
        for x in range(grid.grid_x):
            cell = grid.at(x, y)
            cell.walkable = True
            cell.transparent = True
            cell.tilesprite = 46  # . period
            cell.color = mcrfpy.Color(50, 50, 50)
    
    # Create some walls to make pathfinding interesting
    # Vertical wall
    for y in range(5, 15):
        cell = grid.at(10, y)
        cell.walkable = False
        cell.transparent = False
        cell.tilesprite = 219  # Block
        cell.color = mcrfpy.Color(100, 100, 100)
    
    # Horizontal wall
    for x in range(5, 15):
        if x != 10:  # Leave a gap
            cell = grid.at(x, 10)
            cell.walkable = False
            cell.transparent = False
            cell.tilesprite = 219
            cell.color = mcrfpy.Color(100, 100, 100)
    
    return grid

def test_basic_dijkstra():
    """Test basic Dijkstra functionality"""
    print("\n=== Testing Basic Dijkstra ===")
    
    grid = create_test_grid()
    
    # Compute Dijkstra map from position (5, 5)
    root_x, root_y = 5, 5
    print(f"Computing Dijkstra map from root ({root_x}, {root_y})")
    grid.compute_dijkstra(root_x, root_y)
    
    # Test getting distances to various points
    test_points = [
        (5, 5),    # Root position (should be 0)
        (6, 5),    # Adjacent (should be 1)
        (7, 5),    # Two steps away
        (15, 15),  # Far corner
        (10, 10),  # On a wall (should be unreachable)
    ]
    
    print("\nDistances from root:")
    for x, y in test_points:
        distance = grid.get_dijkstra_distance(x, y)
        if distance is None:
            print(f"  ({x:2}, {y:2}): UNREACHABLE")
        else:
            print(f"  ({x:2}, {y:2}): {distance:.1f}")
    
    # Test getting paths
    print("\nPaths to root:")
    for x, y in [(15, 5), (15, 15), (5, 15)]:
        path = grid.get_dijkstra_path(x, y)
        if path:
            print(f"  From ({x}, {y}): {len(path)} steps")
            # Show first few steps
            for i, (px, py) in enumerate(path[:3]):
                print(f"    Step {i+1}: ({px}, {py})")
            if len(path) > 3:
                print(f"    ... {len(path)-3} more steps")
        else:
            print(f"  From ({x}, {y}): No path found")

def test_libtcod_interface():
    """Test the libtcod module interface"""
    print("\n=== Testing libtcod Interface ===")
    
    grid = create_test_grid()
    
    # Use libtcod functions
    print("Using libtcod.dijkstra_* functions:")
    
    # Create dijkstra context (returns grid)
    dijkstra = libtcod.dijkstra_new(grid)
    print(f"Created Dijkstra context: {type(dijkstra)}")
    
    # Compute from a position
    libtcod.dijkstra_compute(grid, 10, 2)
    print("Computed Dijkstra map from (10, 2)")
    
    # Get distance using libtcod
    distance = libtcod.dijkstra_get_distance(grid, 10, 17)
    print(f"Distance to (10, 17): {distance}")
    
    # Get path using libtcod
    path = libtcod.dijkstra_path_to(grid, 10, 17)
    print(f"Path from (10, 17) to root: {len(path) if path else 0} steps")

def test_multi_target_scenario():
    """Test fleeing/approaching multiple targets"""
    print("\n=== Testing Multi-Target Scenario ===")
    
    grid = create_test_grid()
    
    # Place three "threats" and compute their Dijkstra maps
    threats = [(3, 3), (17, 3), (10, 17)]
    
    print("Computing threat distances...")
    threat_distances = []
    
    for i, (tx, ty) in enumerate(threats):
        # Mark threat position
        cell = grid.at(tx, ty)
        cell.tilesprite = 84  # T for threat
        cell.color = mcrfpy.Color(255, 0, 0)
        
        # Compute Dijkstra from this threat
        grid.compute_dijkstra(tx, ty)
        
        # Store distances for all cells
        distances = {}
        for y in range(grid.grid_y):
            for x in range(grid.grid_x):
                d = grid.get_dijkstra_distance(x, y)
                if d is not None:
                    distances[(x, y)] = d
        
        threat_distances.append(distances)
        print(f"  Threat {i+1} at ({tx}, {ty}): {len(distances)} reachable cells")
    
    # Find safest position (farthest from all threats)
    print("\nFinding safest position...")
    best_pos = None
    best_min_dist = 0
    
    for y in range(grid.grid_y):
        for x in range(grid.grid_x):
            # Skip if not walkable
            if not grid.at(x, y).walkable:
                continue
            
            # Get minimum distance to any threat
            min_dist = float('inf')
            for threat_dist in threat_distances:
                if (x, y) in threat_dist:
                    min_dist = min(min_dist, threat_dist[(x, y)])
            
            # Track best position
            if min_dist > best_min_dist and min_dist != float('inf'):
                best_min_dist = min_dist
                best_pos = (x, y)
    
    if best_pos:
        print(f"Safest position: {best_pos} (min distance to threats: {best_min_dist:.1f})")
        # Mark safe position
        cell = grid.at(best_pos[0], best_pos[1])
        cell.tilesprite = 83  # S for safe
        cell.color = mcrfpy.Color(0, 255, 0)

def run_test(runtime):
    """Timer callback to run tests after scene loads"""
    test_basic_dijkstra()
    test_libtcod_interface()
    test_multi_target_scenario()
    
    print("\n=== Dijkstra Implementation Test Complete ===")
    print("✓ Basic Dijkstra computation works")
    print("✓ Distance queries work") 
    print("✓ Path finding works")
    print("✓ libtcod interface works")
    print("✓ Multi-target scenarios work")
    
    # Take screenshot
    try:
        from mcrfpy import automation
        automation.screenshot("dijkstra_test.png")
        print("\nScreenshot saved: dijkstra_test.png")
    except:
        pass
    
    sys.exit(0)

# Main execution
print("McRogueFace Dijkstra Pathfinding Test")
print("=====================================")

# Set up scene
grid = create_test_grid()
ui = mcrfpy.sceneUI("dijkstra_test")
ui.append(grid)

# Add title
title = mcrfpy.Caption("Dijkstra Pathfinding Test", 10, 10)
title.fill_color = mcrfpy.Color(255, 255, 255)
ui.append(title)

# Set timer to run tests
mcrfpy.setTimer("test", run_test, 100)

# Show scene
mcrfpy.setScene("dijkstra_test")