using System.Text.Json;

namespace Lumi.Companion.SongOverlay;

internal sealed class SongOverlaySettingsStore(string path)
{
    private readonly SemaphoreSlim _gate = new(1, 1);
    public SongOverlaySettings Current { get; private set; } = new();

    public async Task LoadAsync(CancellationToken cancellationToken = default)
    {
        if (!File.Exists(path)) return;
        try
        {
            Current = JsonSerializer.Deserialize<SongOverlaySettings>(
                await File.ReadAllBytesAsync(path, cancellationToken),
                SongOverlayJson.Options) ?? new();
        }
        catch (JsonException)
        {
            Current = new();
        }
    }

    public void Save(SongOverlaySettings settings)
    {
        _gate.Wait();
        try
        {
            Directory.CreateDirectory(Path.GetDirectoryName(path)!);
            var temporary = $"{path}.{Environment.ProcessId}.tmp";
            try
            {
                File.WriteAllBytes(temporary, JsonSerializer.SerializeToUtf8Bytes(settings, SongOverlayJson.Options));
                File.Move(temporary, path, true);
            }
            finally { File.Delete(temporary); }
            Current = settings;
        }
        finally { _gate.Release(); }
    }

    public async Task SaveAsync(SongOverlaySettings settings, CancellationToken cancellationToken = default)
    {
        await _gate.WaitAsync(cancellationToken);
        try
        {
            Directory.CreateDirectory(Path.GetDirectoryName(path)!);
            var temporary = $"{path}.{Environment.ProcessId}.tmp";
            try
            {
                await File.WriteAllBytesAsync(temporary, JsonSerializer.SerializeToUtf8Bytes(settings, SongOverlayJson.Options), cancellationToken);
                File.Move(temporary, path, true);
            }
            finally { File.Delete(temporary); }
            Current = settings;
        }
        finally { _gate.Release(); }
    }
}

internal static class SongOverlayJson
{
    public static readonly JsonSerializerOptions Options = new(JsonSerializerDefaults.Web)
    {
        DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
    };
}
