using Cthangover.Core.Events;
using Cthangover.Core.Scenes;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.Utils;
using Godot;
using Cthangover.Core.UI.Messages;
namespace Cthangover.Mods.Interface.Messages
{
///
/// Static factory for floating UI messages (like "Quest updated" or item
/// pickup notifications). Manages a cycling position index of 0-5 so
/// consecutive messages stack vertically without overlapping. Each message
/// is instantiated from message.tscn and parented to the Background node
/// (found via scene tree search). Without that shell, only the text is buffered for its return;
/// no detached native controls are allocated. Visible messages auto-fade and self-destruct
/// via UiMessage's OnUpdate.
///
public static class MessagesHelper
{
private const int maxMessageIndex = 5;
private static int lastMessageIndex = 0;
private static ModScenePrefab prefab;
private static int GetNextIndex(int index)
{
if (index++ >= maxMessageIndex)
index = 0;
return index;
}
private static float GetPositionByLastIndex(int index)
{
return (index - 1) * 60;
}
///
/// Resets the cycling position index to 0. Call when UI state resets
/// to prevent messages from accumulating at high Y positions.
///
public static void ClearLastIndex()
{
lastMessageIndex = 0;
}
///
/// Shows a message in the default warning colour at the next vertical slot.
///
/// The message text to display.
/// Fade speed multiplier (higher = faster fade, default 1).
public static void AddMessage(string text, float speed = 1f)
{
AddMessage(text, UiTokens.Warning, speed);
}
///
/// Shows a message with a custom color at the next vertical slot.
/// Messages auto-fade and self-destruct after ~3 seconds of display plus
/// a fade duration determined by .
///
/// The message text to display.
/// The text color.
/// Fade speed multiplier (higher = faster fade, default 1).
public static void AddMessage(string text, Color color, float speed = 1f)
{
var nextIndex = GetNextIndex(lastMessageIndex);
AddMessage(GetPositionByLastIndex(nextIndex), text, color, speed);
lastMessageIndex = nextIndex;
}
///
/// Shows a message in the default warning colour at a specific vertical
/// position, bypassing the cycling slot system.
///
/// Y-offset in pixels for this message.
/// The message text to display.
/// Fade speed multiplier (default 1).
public static void AddMessage(float position, string text, float speed = 1f)
{
AddMessage(position, text, UiTokens.Warning, speed);
}
///
/// Instantiates a from message.tscn, parents
/// it to the Background node, and configures it for display and auto-fade.
/// A scene without a background queues the text until the shell returns.
///
/// Y-offset in pixels for this message.
/// The message text to display.
/// The text color.
/// Fade speed multiplier (default 1).
public static void AddMessage(float position, string text, Color color, float speed = 1f)
{
// Battle and menu scenes may have no shell background. Resolve the owner before allocating native nodes.
var tree = SceneContextNode.Instance?.GetTree();
var background = tree?.Root.FindChild("Background", true, false) as Control
?? tree?.GetFirstNodeInGroup("Background") as Control;
if (background == null)
{
// Keep battle rewards until the shell returns, without creating a detached message tree.
NotificationBuffer.Add(text);
return;
}
prefab ??= new ModScenePrefab("scenes/ui/message.tscn");
var instance = prefab.Instantiate();
if (instance != null)
{
background.AddChild(instance);
instance.Setup(position, text, speed, color);
}
ModEventBus.Publish(new NotificationRequestedEvent
{
Text = text,
Category = "message",
});
}
}
}