using System;
using System.Collections;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace BulletHellTemplate
{
///
/// Manages the Battle Pass UI, including displaying items, XP, error messages, and handling popups.
///
public class UIBattlePass : MonoBehaviour
{
[Header("Battle Pass Items")]
public BattlePassItem[] battlePassItems;
public PassEntry passEntryPrefab;
public Transform containerPassItems;
[Header("UI Elements")]
public TextMeshProUGUI errorMessage;
public TextMeshProUGUI levelText;
public TextMeshProUGUI xpText;
public Image xpProgressBar;
public TextMeshProUGUI currentSeason;
public TextMeshProUGUI remainingSeasonTime;
public TextMeshProUGUI endSeasonText;
public GameObject ButtonBuyPassVisual;
[Header("Purchase Pass Popup")]
public GameObject purchasePopup;
public Image purchaseIconCurrency;
public TextMeshProUGUI purchaseTextPrice;
[Header("Claim Reward Popup")]
public GameObject claimPopup;
public Image claimIconReward;
public TextMeshProUGUI claimTextRewardAmount;
[Header("Translated Labels and Fallbacks")]
public string levelLabelFallback = "Level: {0}";
[Tooltip("Translation for the 'Level: {0}' label.")]
public NameTranslatedByLanguage[] levelLabelTranslated;
[Space]
[Tooltip("Translation for the 'XP: {0} / {1}' label.")]
public string xpLabelFallback = "XP: {0} / {1}";
public NameTranslatedByLanguage[] xpLabelTranslated;
[Space]
[Tooltip("Translation for the 'Season: {0}' label.")]
public string seasonLabelFallback = "Season: {0}";
public NameTranslatedByLanguage[] seasonLabelTranslated;
[Space]
[Tooltip("Translation for the 'Season ended' label.")]
public string seasonEndedLabelFallback = "Season ended";
public NameTranslatedByLanguage[] seasonEndedLabelTranslated;
[Space]
[Tooltip("Translation for the 'Ends: ' prefix label.")]
public string seasonEndsLabelFallback = "Ends: ";
public NameTranslatedByLanguage[] seasonEndsLabelTranslated;
private bool firstLoad;
public static UIBattlePass Singleton;
[Header("Events")]
[Tooltip("Event invoked when the menu is opened.")]
public UnityEvent OnOpenMenu;
[Tooltip("Event invoked when the menu is closed.")]
public UnityEvent OnCloseMenu;
private void Awake()
{
if (Singleton == null)
{
Singleton = this;
}
LoadSeasonInfoAsync();
}
///
/// Loads season information and checks for updates.
///
public async void LoadSeasonInfoAsync()
{
await BattlePassManager.Singleton.CheckAndUpdateSeasonAsync();
firstLoad = true;
}
private void OnEnable()
{
if (firstLoad)
{
BattlePassManager.Singleton.OnXPChanged += OnXPChanged;
LoadBattlePassItems();
}
errorMessage.text = "";
}
private void OnDisable()
{
BattlePassManager.Singleton.OnXPChanged -= OnXPChanged;
}
///
/// Starts a coroutine to update the remaining season time after the UI has been rendered.
///
/// IEnumerator for coroutine.
private IEnumerator StartRemainingTimeCoroutineAfterFrame()
{
yield return null;
StartCoroutine(GetRemainingSeasonTime());
}
///
/// Retrieves and updates the remaining season time from PlayerPrefs.
///
/// IEnumerator for coroutine.
public IEnumerator GetRemainingSeasonTime()
{
string savedEndTimeStr = BattlePassManager.GetRemainingSeasonTimeLocally();
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
if (string.IsNullOrEmpty(savedEndTimeStr))
{
Debug.LogWarning("No season end time found. Please ensure it is saved locally.");
yield break;
}
DateTime seasonEndTime = DateTime.Parse(savedEndTimeStr, null, System.Globalization.DateTimeStyles.RoundtripKind);
while (true)
{
TimeSpan remainingTime = seasonEndTime - DateTime.UtcNow;
if (remainingTime.TotalSeconds <= 0)
{
Debug.Log("The current season has ended.");
BattlePassManager.SetPlayerBattlePassSeasonEnded();
string seasonEndedLabel = GetTranslatedString(seasonEndedLabelTranslated, seasonEndedLabelFallback, currentLang);
remainingSeasonTime.text = seasonEndedLabel;
yield break;
}
string seasonEndsLabel = GetTranslatedString(seasonEndsLabelTranslated, seasonEndsLabelFallback, currentLang);
string formattedTime = seasonEndsLabel + $"{remainingTime.Days}d {remainingTime.Hours}h {remainingTime.Minutes}m : {remainingTime.Seconds:D2}s";
if (remainingSeasonTime != null)
{
remainingSeasonTime.text = formattedTime;
}
yield return new WaitForSeconds(1f);
}
}
///
/// Updates the XP UI elements and progress bars for each PassEntry.
///
public void UpdateXPUI()
{
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
string translatedSeasonLabel = GetTranslatedString(seasonLabelTranslated, seasonLabelFallback, currentLang);
currentSeason.text = string.Format(translatedSeasonLabel, BattlePassManager.GetPlayerBattlePassSeason());
StartCoroutine(StartRemainingTimeCoroutineAfterFrame());
if (endSeasonText != null && BattlePassManager.HasBattlePassSeasonEnded())
{
endSeasonText.gameObject.SetActive(true);
}
int currentLevel = BattlePassManager.Singleton.currentLevel;
int currentXP = BattlePassManager.Singleton.currentXP;
int xpForNextLevel = BattlePassManager.Singleton.xpForNextLevel;
string translatedLevelLabel = GetTranslatedString(levelLabelTranslated, levelLabelFallback, currentLang);
string translatedXpLabel = GetTranslatedString(xpLabelTranslated, xpLabelFallback, currentLang);
levelText.text = string.Format(translatedLevelLabel, currentLevel);
xpText.text = string.Format(translatedXpLabel, currentXP, xpForNextLevel);
xpProgressBar.fillAmount = (float)currentXP / xpForNextLevel;
foreach (Transform child in containerPassItems)
{
PassEntry passEntry = child.GetComponent();
if (passEntry != null)
{
passEntry.UpdateProgressBar();
}
}
}
///
/// Loads the Battle Pass items and instantiates PassEntry prefabs with translated titles and descriptions.
///
public async void LoadBattlePassItems()
{
ClearPassItems();
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
for (int i = 0; i < battlePassItems.Length; i++)
{
BattlePassItem item = battlePassItems[i];
PassEntry passEntry = Instantiate(passEntryPrefab, containerPassItems);
bool isUnlocked = BattlePassManager.Singleton.IsBattlePassUnlocked() || item.rewardTier == BattlePassItem.RewardTier.Free;
bool isClaimed = BattlePassManager.Singleton.IsRewardClaimed(item.passId);
string translatedTitle = item.GetTranslatedTitle(currentLang);
string translatedDescription = item.GetTranslatedDescription(currentLang);
passEntry.SetPassItemInfo(item, item.passId, translatedTitle, translatedDescription, item.itemIcon, item.rewardTier == BattlePassItem.RewardTier.Paid, isUnlocked, isClaimed, i);
}
await Task.Delay(100);
UpdateBuyPassButtonVisibility();
UpdateXPUI();
}
///
/// Adds test XP for debugging and reloads Battle Pass items.
///
public void TestEXPPass()
{
BattlePassManager.Singleton.AddTestXP(300);
LoadBattlePassItems();
}
///
/// Clears all PassEntry objects from the container.
///
public void ClearPassItems()
{
foreach (Transform child in containerPassItems)
{
Destroy(child.gameObject);
}
}
///
/// Coroutine to hide the error message after a specified delay.
///
/// Delay in seconds before hiding the error message.
/// IEnumerator for coroutine.
private IEnumerator HideErrorMessageAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
errorMessage.text = "";
}
///
/// Handles the button click to purchase the Battle Pass.
///
public async void OnClickPurchaseBattlePass()
{
string error = await BattlePassManager.Singleton.UnlockBattlePass();
if (string.IsNullOrEmpty(error))
{
LoadBattlePassItems();
UpdateXPUI();
purchasePopup.SetActive(false);
}
else
{
errorMessage.text = error;
StartCoroutine(HideErrorMessageAfterDelay(3f));
}
}
///
/// Displays the purchase popup with the correct currency icon and price.
///
public void ShowPurchasePopup()
{
purchaseIconCurrency.sprite = MonetizationManager.Singleton.GetCurrencyIcon(BattlePassManager.Singleton.currencyID);
purchaseTextPrice.text = BattlePassManager.Singleton.battlePassPrice.ToString();
purchasePopup.SetActive(true);
}
///
/// Displays the claim popup with the reward details.
///
/// Title of the reward.
/// Icon of the reward.
/// Description of the reward.
public void ShowClaimPopup(string rewardTitle, Sprite rewardIcon, string rewardDescription)
{
claimIconReward.sprite = rewardIcon;
claimTextRewardAmount.text = rewardDescription;
claimPopup.SetActive(true);
}
///
/// Hides the claim popup.
///
public void HideClaimPopup()
{
claimPopup.SetActive(false);
}
///
/// Updates the UI when XP changes.
///
/// Event sender.
/// Event arguments.
private void OnXPChanged(object sender, EventArgs e)
{
UpdateXPUI();
}
///
/// Updates the visibility of the Buy Pass button based on the unlock status.
///
private void UpdateBuyPassButtonVisibility()
{
ButtonBuyPassVisual.SetActive(!BattlePassManager.Singleton.IsBattlePassUnlocked());
}
///
/// Retrieves the translated string based on the provided translations array and fallback.
///
/// Array of translations.
/// Fallback string if no translation is found.
/// Current language identifier.
/// The translated string if available; otherwise, the fallback string.
private string GetTranslatedString(NameTranslatedByLanguage[] translations, string fallback, string currentLang)
{
if (translations != null)
{
foreach (var trans in translations)
{
if (!string.IsNullOrEmpty(trans.LanguageId) &&
trans.LanguageId.Equals(currentLang, StringComparison.OrdinalIgnoreCase) &&
!string.IsNullOrEmpty(trans.Translate))
{
return trans.Translate;
}
}
}
return fallback;
}
}
}