using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Theriapolis.Game.Screens;

/// <summary>
/// Manages a stack of IScreen instances.
/// Only the top screen receives Update and Draw calls.
/// Push/Pop are deferred to the start of the next frame to avoid mid-loop mutation.
/// </summary>
public sealed class ScreenManager
{
    private readonly Game1 _game;
    private readonly Stack<IScreen> _stack = new();

    private IScreen? _pendingPush;
    private int _pendingPops;  // count rather than bool — multiple Pops queued in one frame all apply

    public ScreenManager(Game1 game)
    {
        _game = game;
    }

    public IScreen? Current => _stack.Count > 0 ? _stack.Peek() : null;

    public void Push(IScreen screen)
    {
        _pendingPush = screen;
    }

    public void Pop()
    {
        _pendingPops++;
    }

    /// <summary>Process any pending push/pop, then update the current screen.</summary>
    public void Update(GameTime gameTime)
    {
        // Apply deferred transitions — drain all pending pops before any push.
        bool popped = false;
        while (_pendingPops > 0 && _stack.Count > 0)
        {
            var top = _stack.Pop();
            top.Deactivate();
            _pendingPops--;
            popped = true;
        }
        _pendingPops = 0;
        // Only call Reactivate once after a pop chain — not every frame.
        if (popped && _stack.TryPeek(out var back)) back.Reactivate();

        if (_pendingPush is not null)
        {
            _stack.TryPeek(out var cur);
            cur?.Deactivate();
            _pendingPush.Initialize(_game);
            _stack.Push(_pendingPush);
            _pendingPush = null;
        }

        Current?.Update(gameTime);
    }

    public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
    {
        Current?.Draw(gameTime, spriteBatch);
    }
}
