using System;
using Unity.BossRoom.Gameplay.Configuration;
using Unity.BossRoom.Gameplay.UI;
using Unity.BossRoom.UnityServices.Auth;
using Unity.BossRoom.UnityServices.Lobbies;
using Unity.BossRoom.Utils;
using Unity.Services.Authentication;
using Unity.Services.Core;
using UnityEngine;
using UnityEngine.UI;
using VContainer;
using VContainer.Unity;
namespace Unity.BossRoom.Gameplay.GameState
{
///
/// Game Logic that runs when sitting at the MainMenu. This is likely to be "nothing", as no game has been started. But it is
/// nonetheless important to have a game state, as the GameStateBehaviour system requires that all scenes have states.
///
/// OnNetworkSpawn() won't ever run, because there is no network connection at the main menu screen.
/// Fortunately we know you are a client, because all players are clients when sitting at the main menu screen.
///
public class ClientMainMenuState : GameStateBehaviour
{
public override GameState ActiveState => GameState.MainMenu;
[SerializeField]
NameGenerationData m_NameGenerationData;
[SerializeField]
LobbyUIMediator m_LobbyUIMediator;
[SerializeField]
IPUIMediator m_IPUIMediator;
[SerializeField]
Button m_LobbyButton;
[SerializeField]
GameObject m_SignInSpinner;
[SerializeField]
UIProfileSelector m_UIProfileSelector;
[SerializeField]
UITooltipDetector m_UGSSetupTooltipDetector;
[Inject]
AuthenticationServiceFacade m_AuthServiceFacade;
[Inject]
LocalLobbyUser m_LocalUser;
[Inject]
LocalLobby m_LocalLobby;
[Inject]
ProfileManager m_ProfileManager;
protected override void Awake()
{
base.Awake();
m_LobbyButton.interactable = false;
m_LobbyUIMediator.Hide();
if (string.IsNullOrEmpty(Application.cloudProjectId))
{
OnSignInFailed();
return;
}
TrySignIn();
}
protected override void Configure(IContainerBuilder builder)
{
base.Configure(builder);
builder.RegisterComponent(m_NameGenerationData);
builder.RegisterComponent(m_LobbyUIMediator);
builder.RegisterComponent(m_IPUIMediator);
}
private async void TrySignIn()
{
try
{
var unityAuthenticationInitOptions =
m_AuthServiceFacade.GenerateAuthenticationOptions(m_ProfileManager.Profile);
await m_AuthServiceFacade.InitializeAndSignInAsync(unityAuthenticationInitOptions);
OnAuthSignIn();
m_ProfileManager.onProfileChanged += OnProfileChanged;
}
catch (Exception)
{
OnSignInFailed();
}
}
private void OnAuthSignIn()
{
m_LobbyButton.interactable = true;
m_UGSSetupTooltipDetector.enabled = false;
m_SignInSpinner.SetActive(false);
Debug.Log($"Signed in. Unity Player ID {AuthenticationService.Instance.PlayerId}");
m_LocalUser.ID = AuthenticationService.Instance.PlayerId;
// The local LobbyUser object will be hooked into UI before the LocalLobby is populated during lobby join, so the LocalLobby must know about it already when that happens.
m_LocalLobby.AddUser(m_LocalUser);
}
private void OnSignInFailed()
{
if (m_LobbyButton)
{
m_LobbyButton.interactable = false;
m_UGSSetupTooltipDetector.enabled = true;
}
if (m_SignInSpinner)
{
m_SignInSpinner.SetActive(false);
}
}
protected override void OnDestroy()
{
m_ProfileManager.onProfileChanged -= OnProfileChanged;
base.OnDestroy();
}
async void OnProfileChanged()
{
m_LobbyButton.interactable = false;
m_SignInSpinner.SetActive(true);
await m_AuthServiceFacade.SwitchProfileAndReSignInAsync(m_ProfileManager.Profile);
m_LobbyButton.interactable = true;
m_SignInSpinner.SetActive(false);
Debug.Log($"Signed in. Unity Player ID {AuthenticationService.Instance.PlayerId}");
// Updating LocalUser and LocalLobby
m_LocalLobby.RemoveUser(m_LocalUser);
m_LocalUser.ID = AuthenticationService.Instance.PlayerId;
m_LocalLobby.AddUser(m_LocalUser);
}
public void OnStartClicked()
{
m_LobbyUIMediator.ToggleJoinLobbyUI();
m_LobbyUIMediator.Show();
}
public void OnDirectIPClicked()
{
m_LobbyUIMediator.Hide();
m_IPUIMediator.Show();
}
public void OnChangeProfileClicked()
{
m_UIProfileSelector.Show();
}
}
}