using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;
///
/// class that loads leaderboard data and displays it in the UI
///
public class LeaderboardUI : MonoBehaviour
{
///
/// maximum number of entries to display in the leaderboard
///
public const int MaxEntries = 50;
///
/// uxml template for a leaderboard entry
///
[SerializeField] private VisualTreeAsset leaderboardEntryTemplate;
///
/// leaderboard data
///
private List _leaderboardData = new(MaxEntries);
///
/// reference to the leaderboard scroll view
///
private ScrollView _leaderboardScrollView;
///
/// register callbacks
///
private void OnEnable()
{
UIManager.Instance.RegisterOnDisplayStateChangeCallback((_, newState) =>
{
if (newState == UIManager.DisplayState.LeaderboardView) LoadLeaderboardData();
});
_leaderboardScrollView = UIManager.Instance.UI.Q("LeaderboardListContent");
if (_leaderboardScrollView == null)
throw new NullReferenceException("leaderboard scroll view not found in the UI");
}
///
/// load leaderboard data from the backend
///
private void LoadLeaderboardData()
{
if (GameManager.Instance.Backend.Status != Backend.FirebaseConnectionStatus.Connected)
{
Debug.LogError("attempted to load leaderboard data without a connection to the backend");
RenderLeaderboardData("Not connected to the backend, can't load leaderboard data.");
return;
}
GameManager.Instance.Backend.GetLeaderboard((result, entries) =>
{
if (result == Backend.TransactionResult.Ok)
{
_leaderboardData = entries;
RenderLeaderboardData();
}
else
{
Debug.LogError("failed to load leaderboard data");
RenderLeaderboardData("An error occured, couldn't load leaderboard data.");
}
});
}
///
/// render leaderboard data in the UI
///
/// message to display in the leaderboard in lieu of actual data
///
/// thrown when the leaderboard scroll view is missing or when the leaderboard
/// entry
///
private void RenderLeaderboardData(string message = "")
{
_leaderboardScrollView.Clear();
if (!string.IsNullOrEmpty(message))
{
Debug.Log($"rendering leaderboard with message entry-in-lieu: '{message}'");
_leaderboardScrollView.Add(BuildEntryElement("", message, ""));
return;
}
Debug.Log($"rendering {_leaderboardData.Count} leaderboard entries");
foreach (var (entry, index) in _leaderboardData.Take(MaxEntries).Reverse()
.Select((entry, index) => (entry, index)))
_leaderboardScrollView.Add(BuildEntryElement((index + 1).ToString(), entry.Username, $"{entry.Rating:F3}"));
}
///
/// build a leaderboard entry element
///
/// leaderboard position as a string
/// score holder's username
/// score holder's rating
/// a visual element representing a leaderboard entry
/// thrown when the leaderboard entry template is missing required elements
private TemplateContainer BuildEntryElement(string position, string username, string rating)
{
var template = leaderboardEntryTemplate.Instantiate();
var templatePositionText = template.Q