using System;
using System.Collections.Generic;
using KernelPanic.Core;
using KernelPanic.Meta;
using UnityEngine;
using UnityEngine.TextCore.Text;
using UnityEngine.UIElements;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace KernelPanic.UI
{
///
/// Binds the main menu terminal UI document and routes command activation between panels.
///
[RequireComponent(typeof(UIDocument))]
public sealed class MainMenuController : MonoBehaviour
{
private const string HiddenClassName = "hidden";
private const string SelectedClassName = "selected";
private const string CursorOnClassName = "cursor-on";
private const float BootIntroSeconds = 1.5f;
private static bool bootIntroPlayed;
[SerializeField] private FontAsset monospaceFont; // TODO: Assign a real monospace FontAsset when typography assets exist.
[SerializeField] private string motdBody = "unstable userspace detected; keep a rollback shell open.";
[SerializeField] private FeaturedUnitPanel featuredUnitPanel = new();
private readonly List commandEntries = new();
private UIDocument document;
private VisualElement root;
private VisualElement shellRoot;
private VisualElement bootIntroPanel;
private VisualElement mainMenuPanel;
private VisualElement collectionPanel;
private VisualElement gachaPanel;
private VisualElement settingsPanel;
private VisualElement eventBanner;
private VisualElement backgroundLogLayer;
private Label appIdLabel;
private Label entropyLabel;
private Label pullTokensLabel;
private Label titleCursorLabel;
private Label promptCursorLabel;
private Label bootIntroLogLabel;
private Label motdBodyLabel;
private VisualElement motdBlock;
private Button collectionBackButton;
private Button gachaBackButton;
private Button settingsBackButton;
private EntropyWallet wallet;
private GachaService gachaService;
private PlayerCollection playerCollection;
private BackgroundLogRingBuffer backgroundLog;
private IEventBannerSource eventBannerSource;
private int selectedCommandIndex;
private float bootIntroElapsed;
private int bootIntroCharacterCount;
private bool cursorVisible;
private bool suppressNextClick;
private string bootIntroCopy;
private IVisualElementScheduledItem blinkSchedule;
private IVisualElementScheduledItem bootIntroSchedule;
public void Initialize(EntropyWallet initializedWallet)
{
wallet = initializedWallet ?? new EntropyWallet();
RefreshCurrencyReadouts();
}
private void Awake()
{
document = GetComponent();
gachaService = new GachaService();
playerCollection = new PlayerCollection(); // TODO: Replace with persistent player-collection service composition.
Initialize(new EntropyWallet()); // TODO: Replace with persistent wallet service composition.
BindElements();
BindCommandEntries();
RegisterCommandEntryCallbacks();
featuredUnitPanel.Bind(root);
ApplyOptionalFont();
}
private void OnEnable()
{
RegisterCallbacks();
root.Focus();
shellRoot.EnableInClassList("reduced-motion", UIPreferences.ReducedMotion);
RefreshStaticText();
RefreshCurrencyReadouts();
RefreshEventBanner();
featuredUnitPanel.Refresh(playerCollection.OwnedUnits);
SelectCommand(0);
ShowMainMenu();
StartAmbientSchedules();
PlayBootIntroIfNeeded();
}
private void OnDisable()
{
UnregisterCallbacks();
blinkSchedule?.Pause();
backgroundLog?.Stop();
bootIntroSchedule?.Pause();
}
private void BindElements()
{
root = document.rootVisualElement;
shellRoot = root.Q("ShellRoot");
bootIntroPanel = root.Q("BootIntroPanel");
mainMenuPanel = root.Q("MainMenuPanel");
collectionPanel = root.Q("CollectionPanel");
gachaPanel = root.Q("GachaPanel");
settingsPanel = root.Q("SettingsPanel");
eventBanner = root.Q("EventBanner");
motdBlock = root.Q("MotdBlock");
backgroundLogLayer = root.Q("BackgroundLogLayer");
backgroundLog = new BackgroundLogRingBuffer(backgroundLogLayer, BootLogCopy.Lines);
appIdLabel = root.Q