using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
using RR.Common.Settings;
using RR.Game2D.Core.Managers;
namespace RR.Common.UI
{
///
/// Контроллер баннера проигрыша.
/// Модальное окно, которое отображается при поражении игрока.
///
public class LoseBannerController : Modal
{
[Header("Элементы баннера проигрыша")]
[SerializeField] private TextMeshProUGUI loseText;
[SerializeField] private TextMeshProUGUI creditText;
[SerializeField] private Button continueButton;
[SerializeField] private TextMeshProUGUI continueButtonText;
[SerializeField] private Button menuButton;
[SerializeField] private TextMeshProUGUI menuButtonText;
[SerializeField] private float continueButtonCountdown = 30f;
[Header("Тексты")]
[SerializeField] private string creditTextFormat = "У вас осталось: {0}";
[SerializeField] private string continueButtonTextFormat = "Продолжить? ({0})";
[SerializeField] private string menuButtonTextFormat = "В меню ({0})";
private RR.Common.Managers.BalanceManager _balanceManager;
private Coroutine _continueCountdownCoroutine;
private bool _isSubscribedToBalance = false;
///
/// Событие, вызываемое при нажатии "Продолжить" или закрытии баннера.
///
public event Action ContinueClicked;
protected override void Awake()
{
base.Awake();
if (continueButton)
{
continueButton.onClick.AddListener(OnContinueButtonClicked);
}
if (menuButton)
{
menuButton.onClick.AddListener(OnMenuButtonClicked);
}
}
protected override void OnEnable()
{
base.OnEnable();
// Инициализируем BalanceManager
if (_balanceManager == null)
{
_balanceManager = GameManager.Instance?.Balance;
}
// Подписываемся на событие только если еще не подписаны
if (_balanceManager != null && !_isSubscribedToBalance)
{
int balance = _balanceManager.CurrentBalance;
if (creditText)
{
creditText.text = string.Format(creditTextFormat, balance);
}
_balanceManager.OnBalanceChanged.AddListener(UnlockContinueButton);
_isSubscribedToBalance = true;
}
}
protected override void OnDisable()
{
// Остановим корутину, если объект деактивируется
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
_continueCountdownCoroutine = null;
}
// Безопасная отписка от события
if (_balanceManager != null && _isSubscribedToBalance)
{
_balanceManager.OnBalanceChanged.RemoveListener(UnlockContinueButton);
_isSubscribedToBalance = false;
}
base.OnDisable();
}
///
/// Показывает баннер проигрыша с указанным временем игры.
///
/// Время игры в секундах
public void ShowLose(float gameTime)
{
// Инициализируем BalanceManager до открытия окна
if (_balanceManager == null)
{
_balanceManager = GameManager.Instance?.Balance;
}
// Подписываемся на событие изменения баланса, если еще не подписаны
if (_balanceManager != null && !_isSubscribedToBalance)
{
_balanceManager.OnBalanceChanged.AddListener(UnlockContinueButton);
_isSubscribedToBalance = true;
}
if (loseText)
{
loseText.text = $"Время игры: {TimeFormatHelper.FormatTime(gameTime)}";
}
if (creditText && _balanceManager != null)
{
creditText.text = string.Format(creditTextFormat, (object)_balanceManager.CurrentBalance);
}
if (continueButtonCountdown <= 0f)
{
ReturnToMainMenu();
return;
}
Button activeButton = ConfigureVisibleButtons();
if (activeButton != null)
{
SetFirstSelected(activeButton);
}
Open();
FocusActiveButton(activeButton);
// Остановим предыдущую корутину, если есть
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
}
_continueCountdownCoroutine = StartCoroutine(ContinueCountdownCoroutine(continueButtonCountdown));
}
private IEnumerator ContinueCountdownCoroutine(float duration)
{
float elapsed = 0f;
int initialSeconds = Mathf.RoundToInt(duration);
UpdateContinueText(initialSeconds);
while (elapsed < duration)
{
float startTime = Time.unscaledTime;
yield return null;
while (Time.unscaledTime - startTime < 1.0f)
{
yield return null;
}
elapsed += 1f;
int remaining = Mathf.Max(0, Mathf.RoundToInt(duration - elapsed));
UpdateContinueText(remaining);
}
// Таймер истёк — закрываем баннер и выходим в меню
Close();
ContinueClicked?.Invoke();
if (GameManager.Instance)
{
GameManager.Instance.SetPause(false);
GameManager.Instance.LoadScene("MainMenu", false);
}
_continueCountdownCoroutine = null;
}
private void UpdateContinueText(int secondsRemaining)
{
if (continueButton != null && continueButton.gameObject.activeSelf && continueButtonText)
{
continueButtonText.text = string.Format(continueButtonTextFormat, secondsRemaining);
}
if (menuButton != null && menuButton.gameObject.activeSelf && menuButtonText)
{
menuButtonText.text = string.Format(menuButtonTextFormat, secondsRemaining);
}
}
private void UnlockContinueButton(int newBalance)
{
if (_balanceManager == null) return;
// Проверяем возможность продолжить через BalanceManager
if (continueButton)
{
continueButton.interactable = _balanceManager.CanContinueGame();
}
// Обновляем текст баланса
if (creditText)
{
creditText.text = string.Format(creditTextFormat, newBalance);
}
}
private void OnContinueButtonClicked()
{
// При клике на "Продолжить" — остановим таймер и продолжим игру
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
_continueCountdownCoroutine = null;
}
Close();
ContinueClicked?.Invoke();
if (GameManager.Instance)
{
GameManager.Instance.SetPause(false);
GameManager.Instance.ContinueGame();
}
}
private void OnMenuButtonClicked()
{
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
_continueCountdownCoroutine = null;
}
ReturnToMainMenu();
}
private Button ConfigureVisibleButtons()
{
bool canContinueGameSetting = SettingsManager.Instance != null
&& SettingsManager.Instance.GetBool("gameplay.canContinueGame");
if (continueButton != null)
{
continueButton.gameObject.SetActive(canContinueGameSetting);
continueButton.interactable = canContinueGameSetting
&& _balanceManager != null
&& _balanceManager.CanContinueGame();
}
if (menuButton != null)
{
menuButton.gameObject.SetActive(!canContinueGameSetting);
menuButton.interactable = true;
}
return canContinueGameSetting ? continueButton : menuButton;
}
private void FocusActiveButton(Button activeButton)
{
if (activeButton == null || !activeButton.gameObject.activeInHierarchy || EventSystem.current == null)
{
return;
}
EventSystem.current.SetSelectedGameObject(null);
EventSystem.current.SetSelectedGameObject(activeButton.gameObject);
activeButton.Select();
}
private void ReturnToMainMenu()
{
Close();
ContinueClicked?.Invoke();
if (GameManager.Instance)
{
GameManager.Instance.SetPause(false);
GameManager.Instance.LoadScene("MainMenu", false);
}
}
}
}