using Microsoft.Xna.Framework.Graphics;
using MrGameEng.Atlases;
using MrGameEng.Graphics;

namespace LittleSim.Content;

/// <summary>
/// Лениво загружает атласы из кэша, собранного <see cref="GameContent.Load"/>, и владеет
/// их текстурами. Регистрируется сервисом — реестр освобождает его при выходе из игры.
/// </summary>
public sealed class ModAtlases : IDisposable
{
    /// <summary>Глубина группировки атласов (сегментов пути в имени атласа) — общая для сборки и поиска.</summary>
    public const int GroupDepth = 2;

    private readonly string _directory;
    private readonly Dictionary<string, TextureAtlas> _loaded = new(
        StringComparer.OrdinalIgnoreCase
    );

    /// <summary>Создаёт реестр над кэш-директорией атласов.</summary>
    public ModAtlases(string directory) => _directory = directory;

    /// <summary>Уже загруженные атласы по имени.</summary>
    public IReadOnlyDictionary<string, TextureAtlas> Loaded => _loaded;

    /// <summary>Атлас по имени (например, "things.plant"); загружается при первом обращении.</summary>
    public TextureAtlas Get(GraphicsDevice device, string name)
    {
        if (!_loaded.TryGetValue(name, out var atlas))
        {
            atlas = TextureAtlas.Load(device, Path.Combine(_directory, name + ".atlas"));
            _loaded.Add(name, atlas);
        }

        return atlas;
    }

    /// <summary>
    /// Регион по ключу текстуры: имя атласа — первые <see cref="GroupDepth"/> сегментов
    /// пути (как при сборке), ключ региона — весь путь.
    /// </summary>
    public Texture2DRegion GetRegion(GraphicsDevice device, string textureKey)
    {
        var segments = textureKey.Split('/');
        var depth = Math.Min(GroupDepth, segments.Length - 1);
        var name = depth == 0 ? "Atlas" : string.Join('.', segments[..depth]);
        return Get(device, name).GetRegion(textureKey);
    }

    /// <inheritdoc />
    public void Dispose()
    {
        foreach (var atlas in _loaded.Values)
        {
            atlas.Dispose();
        }

        _loaded.Clear();
    }
}
