using Core;
using Core.Lifecycle;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Minigames.Airplane.UI
{
///
/// Displays target information: icon and distance remaining to target.
/// Updates in real-time as the airplane moves.
///
public class TargetDisplayUI : ManagedBehaviour
{
#region Inspector References
[Header("UI Elements")]
[Tooltip("Image to display target icon")]
[SerializeField] private Image targetIcon;
[Tooltip("Text to display distance remaining")]
[SerializeField] private TextMeshProUGUI distanceText;
[Header("Display Settings")]
[Tooltip("Format string for distance display (e.g., '{0:F1}m')")]
[SerializeField] private string distanceFormat = "{0:F1}m";
[Tooltip("Update distance every N frames (0 = every frame)")]
[SerializeField] private int updateInterval = 5;
[Header("Debug")]
[SerializeField] private bool showDebugLogs;
#endregion
#region State
private Transform _planeTransform;
private Transform _launchPointTransform;
private Vector3 _targetPosition;
private bool _isActive;
private int _frameCounter;
#endregion
#region Lifecycle
internal override void OnManagedAwake()
{
base.OnManagedAwake();
// Hide by default
Hide();
// Validate references
if (targetIcon == null)
{
Logging.Warning("[TargetDisplayUI] Target icon image not assigned!");
}
if (distanceText == null)
{
Logging.Warning("[TargetDisplayUI] Distance text not assigned!");
}
}
private void Update()
{
if (!_isActive || _planeTransform == null) return;
// Update distance at specified interval
_frameCounter++;
if (updateInterval == 0 || _frameCounter >= updateInterval)
{
_frameCounter = 0;
UpdateDistance();
}
}
#endregion
#region Public API
///
/// Setup the target display with icon and target position.
///
/// Sprite to display as target icon
/// World position of the target
/// Launch point transform (used for distance when plane not available)
public void Setup(Sprite targetSprite, Vector3 targetPosition, Transform launchPoint)
{
_targetPosition = targetPosition;
_launchPointTransform = launchPoint;
// Set icon
if (targetIcon != null && targetSprite != null)
{
targetIcon.sprite = targetSprite;
targetIcon.enabled = true;
}
// Update distance immediately using launch point
UpdateDistance();
if (showDebugLogs)
{
Logging.Debug($"[TargetDisplayUI] Setup with target at {targetPosition}");
}
}
///
/// Start tracking the airplane and updating distance.
/// Note: Does not automatically show UI - call Show() separately.
///
/// Transform of the airplane to track
public void StartTracking(Transform planeTransform)
{
_planeTransform = planeTransform;
_isActive = true;
_frameCounter = 0;
// Update distance immediately if visible
if (gameObject.activeSelf)
{
UpdateDistance();
}
if (showDebugLogs)
{
Logging.Debug("[TargetDisplayUI] Started tracking airplane");
}
}
///
/// Stop tracking the airplane.
/// Note: Does not automatically hide UI - call Hide() separately.
///
public void StopTracking()
{
_isActive = false;
_planeTransform = null;
if (showDebugLogs)
{
Logging.Debug("[TargetDisplayUI] Stopped tracking");
}
}
///
/// Show the UI.
///
public void Show()
{
gameObject.SetActive(true);
}
///
/// Hide the UI.
///
public void Hide()
{
gameObject.SetActive(false);
}
#endregion
#region Internal
///
/// Update the distance text based on current plane position.
/// Uses launch point if plane isn't available yet.
///
private void UpdateDistance()
{
if (distanceText == null) return;
// Use plane position if available, otherwise use launch point
Vector3 currentPosition;
if (_planeTransform != null)
{
currentPosition = _planeTransform.position;
}
else if (_launchPointTransform != null)
{
currentPosition = _launchPointTransform.position;
}
else
{
// No reference available
return;
}
// Calculate horizontal distance (X-axis only for side-scroller)
float distance = Mathf.Abs(_targetPosition.x - currentPosition.x);
// Update text
distanceText.text = string.Format(distanceFormat, distance);
}
///
/// Update distance and ensure UI is shown.
/// Call when showing UI to refresh distance display.
///
public void UpdateAndShow()
{
UpdateDistance();
Show();
}
#endregion
}
}