using PlatypusIdeas.AirPath.Runtime.Events;
using PlatypusIdeas.AirPath.Runtime.Modes;
using TMPro;
using UnityEngine;
namespace PlatypusIdeas.AirPath.Runtime.UI {
/// <summary>
/// Manages all UI elements for the pathfinding system
/// Subscribes to events and updates UI accordingly
/// </summary>
public class PathfindingUIManager : MonoBehaviour {
[Header("UI Elements")]
[SerializeField] private TextMeshProUGUI timeText;
[SerializeField] private TextMeshProUGUI instructionText;
[SerializeField] private TextMeshProUGUI modeText;
[SerializeField] private TextMeshProUGUI statusText;
[Header("UI Settings")]
[SerializeField] private bool showDetailedStatus = true;
[SerializeField] private string defaultInstructionText = "Select a pathfinding mode to begin";
private IPathfindingMode _currentMode;
private PathfindingModeType _currentModeType;
private void Start() {
InitializeUI();
SubscribeToEvents();
}
private void OnDestroy() {
UnsubscribeFromEvents();
}
private void InitializeUI() {
UpdateInstructionText(defaultInstructionText);
UpdateModeDisplay(PathfindingModeType.MouseClick, null);
if (timeText != null) {
timeText.text = "Ready";
}
}
private void SubscribeToEvents() {
this.Subscribe<PathfindingModeChangedEvent>(OnModeChanged);
this.Subscribe<PathCalculatedEvent>(OnPathCalculated);
this.Subscribe<PathRequestedEvent>(OnPathRequested);
this.Subscribe<BoundaryViolationEvent>(OnBoundaryViolation);
this.Subscribe<PathfindingErrorEvent>(OnPathfindingError);
}
private void UnsubscribeFromEvents() {
EventBusExtensions.Unsubscribe<PathfindingModeChangedEvent>(OnModeChanged);
EventBusExtensions.Unsubscribe<PathCalculatedEvent>(OnPathCalculated);
EventBusExtensions.Unsubscribe<PathRequestedEvent>(OnPathRequested);
EventBusExtensions.Unsubscribe<BoundaryViolationEvent>(OnBoundaryViolation);
EventBusExtensions.Unsubscribe<PathfindingErrorEvent>(OnPathfindingError);
}
private void OnModeChanged(PathfindingModeChangedEvent evt) {
_currentMode = evt.ModeInstance;
_currentModeType = evt.NewMode;
UpdateModeDisplay(evt.NewMode, evt.ModeInstance);
// Let the mode set its own instruction through the context callback
Debug.Log($"[UI] Pathfinding mode changed to: {evt.NewMode}");
}
private void OnPathRequested(PathRequestedEvent evt) {
if (timeText != null) {
timeText.text = "Calculating...";
}
}
private void OnPathCalculated(PathCalculatedEvent evt) {
if (timeText != null) {
timeText.text = $"Path found in: {evt.CalculationTime:F0} ms";
}
if (!evt.Success && instructionText != null) {
instructionText.text = "No path found! Try different points.";
}
}
private void OnBoundaryViolation(BoundaryViolationEvent evt) {
if (evt.WasAutoClamped && instructionText != null) {
string warning = $"Warning: {evt.ViolationType} was outside grid bounds and was clamped!";
instructionText.text = warning;
// Reset instruction text after delay
Invoke(nameof(ResetInstructionText), 3f);
}
}
private void OnPathfindingError(PathfindingErrorEvent evt) {
if (evt.IsCritical) {
if (instructionText != null) {
instructionText.text = $"Error: {evt.ErrorMessage}";
}
if (timeText != null) {
timeText.text = "Error";
}
}
Debug.LogError($"[UI] Pathfinding error: {evt.ErrorMessage}", this);
}
private void Update() {
// Update mode status display
if (showDetailedStatus && _currentMode != null && statusText != null) {
statusText.text = _currentMode.GetStatusInfo();
}
}
public void UpdateInstructionText(string text) {
if (instructionText) {
instructionText.text = text;
}
}
private void UpdateModeDisplay(PathfindingModeType modeType, IPathfindingMode modeInstance) {
if (modeText != null) {
string modeName = modeInstance?.ModeName ?? modeType.ToString();
modeText.text = $"Mode: {modeName}";
}
}
private void ResetInstructionText() {
if (_currentMode != null) {
// This will be called by the mode through the context callback
// For now, set a default
UpdateInstructionText($"{_currentMode.ModeName} mode active");
}
}
/// <summary>
/// Public method for modes to update instruction text through context callback
/// </summary>
public static void UpdateInstruction(string text) {
var instance = FindFirstObjectByType<PathfindingUIManager>();
instance?.UpdateInstructionText(text);
}
}
}