namespace YMhut.Box.WinUI.Services;

public sealed class UiPerformanceModeChangedEventArgs(bool isLightMode, string reason) : EventArgs
{
    public bool IsLightMode { get; } = isLightMode;

    public string Reason { get; } = reason;
}

public interface IUiPerformanceCoordinator
{
    bool IsLightMode { get; }

    event EventHandler<UiPerformanceModeChangedEventArgs>? LightModeChanged;

    IDisposable EnterLightMode(string reason);
}

public sealed class UiPerformanceCoordinator : IUiPerformanceCoordinator
{
    private readonly object _gate = new();
    private int _scopeCount;
    private bool _isLightMode;
    private string _lastReason = string.Empty;

    public bool IsLightMode
    {
        get
        {
            lock (_gate)
            {
                return _isLightMode;
            }
        }
    }

    public event EventHandler<UiPerformanceModeChangedEventArgs>? LightModeChanged;

    public IDisposable EnterLightMode(string reason)
    {
        var changed = false;
        lock (_gate)
        {
            _scopeCount++;
            _lastReason = string.IsNullOrWhiteSpace(reason) ? "light-mode" : reason.Trim();
            if (!_isLightMode)
            {
                _isLightMode = true;
                changed = true;
            }
        }

        if (changed)
        {
            LightModeChanged?.Invoke(this, new UiPerformanceModeChangedEventArgs(true, _lastReason));
        }

        return new Scope(this);
    }

    private void ExitLightMode()
    {
        string reason;
        var changed = false;
        lock (_gate)
        {
            if (_scopeCount > 0)
            {
                _scopeCount--;
            }

            reason = _lastReason;
            if (_scopeCount == 0 && _isLightMode)
            {
                _isLightMode = false;
                changed = true;
            }
        }

        if (changed)
        {
            LightModeChanged?.Invoke(this, new UiPerformanceModeChangedEventArgs(false, reason));
        }
    }

    private sealed class Scope(UiPerformanceCoordinator owner) : IDisposable
    {
        private int _disposed;

        public void Dispose()
        {
            if (Interlocked.Exchange(ref _disposed, 1) == 0)
            {
                owner.ExitLightMode();
            }
        }
    }
}
