using UnityEngine;
using UnityEngine.UIElements;

/// <summary>
///     class that handles the side view ui
/// </summary>
public class SideViewUI : MonoBehaviour
{
    /// <summary>
    ///     settings button for showing the settings menu
    /// </summary>
    private Button _accountButton;

    /// <summary>
    ///     text label for showing the player's stable-ish chroma accuracy
    /// </summary>
    private Label _chromaAccuracyText;

    /// <summary>
    ///     text label for showing the player's stable-ish hue accuracy
    /// </summary>
    private Label _hueAccuracyText;

    /// <summary>
    ///     leaderboard button for showing the leaderboard
    /// </summary>
    private Button _leaderboardButton;

    /// <summary>
    ///     text label for showing the player's stable-ish lightness accuracy
    /// </summary>
    private Label _lightnessAccuracyText;

    /// <summary>
    ///     play button for starting the game
    /// </summary>
    private Button _playButton;

    /// <summary>
    ///     text label for showing the player's known name
    /// </summary>
    private Label _playerText;

    /// <summary>
    ///     text label for showing the player's rating
    /// </summary>
    private Label _ratingText;

    /// <summary>
    ///     initialise the ui elements and register the button click event functions
    /// </summary>
    private void OnEnable()
    {
        var ui = GetComponent<UIDocument>().rootVisualElement;

        _playButton = ui.Q<Button>("PlayButton");
        _playButton.clicked += OnPlayButtonClicked;

        _leaderboardButton = ui.Q<Button>("LeaderboardButton");
        _leaderboardButton.clicked += OnLeaderboardButtonClicked;

        _accountButton = ui.Q<Button>("AccountButton");
        _accountButton.clicked += OnAccountButtonClicked;

        _playerText = ui.Q<Label>("PlayerText");
        _ratingText = ui.Q<Label>("RatingText");

        _lightnessAccuracyText = ui.Q<Label>("LightnessAccuracyText");
        _chromaAccuracyText = ui.Q<Label>("ChromaAccuracyText");
        _hueAccuracyText = ui.Q<Label>("HueAccuracyText");

        GameManager.Instance.Backend.RegisterOnSignOutCallback(() =>
        {
            RenderFromPlayerData(GameManager.Instance.Data);
        });
        GameManager.Instance.RegisterOnLocalPlayerDataChangeCallback(RenderFromPlayerData);
    }

    /// <summary>
    ///     function to show the play view
    /// </summary>
    private static void OnPlayButtonClicked()
    {
        GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.GameView);
    }

    /// <summary>
    ///     function to show the leaderboard view
    /// </summary>
    private static void OnLeaderboardButtonClicked()
    {
        GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.LeaderboardView);
    }

    /// <summary>
    ///     function to show the account view
    /// </summary>
    private static void OnAccountButtonClicked()
    {
        GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.AccountView);
    }

    /// <summary>
    ///     function to update the ui with the latest data
    /// </summary>
    private void RenderFromPlayerData(LocalPlayerData data)
    {
        Debug.Log("updating SideView > AccountSection with new player data");

        // calculate averages from both recent local scores and online scores
        var totalLightnessAcc = 0f;
        var totalChromaAcc = 0f;
        var totalHueAcc = 0f;
        var totalGames = 0;

        // average out all the scores we have to get a stable-ish average

        foreach (var localScore in data.RecentLocalScores)
        {
            totalLightnessAcc += localScore.AvgLightnessAccuracy;
            totalChromaAcc += localScore.AvgChromaAccuracy;
            totalHueAcc += localScore.AvgHueAccuracy;
            totalGames++;
        }

        foreach (var onlineScore in data.RecentOnlineScores)
        {
            totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
            totalChromaAcc += onlineScore.AvgChromaAccuracy;
            totalHueAcc += onlineScore.AvgHueAccuracy;
            totalGames++;
        }

        foreach (var onlineScore in data.BestOnlineScores)
        {
            totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
            totalChromaAcc += onlineScore.AvgChromaAccuracy;
            totalHueAcc += onlineScore.AvgHueAccuracy;
            totalGames++;
        }

        Debug.Log($"tL={totalLightnessAcc} tC={totalChromaAcc} tH={totalHueAcc} tG={totalGames}");
        if (totalGames == 0) totalGames = 1;
        var lightnessAcc = totalLightnessAcc / totalGames;
        var chromaAcc = totalChromaAcc / totalGames;
        var hueAcc = totalHueAcc / totalGames;
        var playerText = GameManager.Instance.Backend.IsSignedIn
            ? data.LastKnownUsername
            : $"{data.LastKnownUsername} (Not Signed In)";
        var rating = data.CalculateUserRating();

        // finally, set the labels
        _playerText.text = playerText;
        _ratingText.text = $"{rating:F3}";
        _lightnessAccuracyText.text = $"{lightnessAcc:F2}%";
        _chromaAccuracyText.text = $"{chromaAcc:F2}%";
        _hueAccuracyText.text = $"{hueAcc:F2}%";
    }
}