namespace Ehwrj.Core.Services;

public interface IWarThunderClient
{
    Task<string> GetMapInfoAsync(CancellationToken cancellationToken);
    Task<string> GetObjectsAsync(CancellationToken cancellationToken);
    Task<byte[]> GetMapImageAsync(CancellationToken cancellationToken);
    Task<string?> TryGetStateAsync(CancellationToken cancellationToken);
    Task<string?> TryGetHudMessagesAsync(CancellationToken cancellationToken);
    Task<string?> TryGetGameChatAsync(CancellationToken cancellationToken);
}

public sealed class WarThunderClient : IWarThunderClient, IDisposable
{
    private readonly HttpClient _httpClient;
    private readonly bool _ownsClient;

    public WarThunderClient()
        : this(new Uri("http://127.0.0.1:8111/"))
    {
    }

    public WarThunderClient(Uri baseAddress)
        : this(new HttpClient
        {
            BaseAddress = baseAddress,
            Timeout = TimeSpan.FromMilliseconds(900)
        }, ownsClient: true)
    {
    }

    public WarThunderClient(HttpClient httpClient, bool ownsClient = false)
    {
        _httpClient = httpClient;
        _ownsClient = ownsClient;

        if (_httpClient.BaseAddress is null)
        {
            _httpClient.BaseAddress = new Uri("http://127.0.0.1:8111/");
        }

        LoopbackGuard.EnsureLoopbackHttp(_httpClient.BaseAddress, nameof(httpClient));
    }

    public Task<string> GetMapInfoAsync(CancellationToken cancellationToken)
    {
        return _httpClient.GetStringAsync("map_info.json", cancellationToken);
    }

    public Task<string> GetObjectsAsync(CancellationToken cancellationToken)
    {
        return _httpClient.GetStringAsync("map_obj.json", cancellationToken);
    }

    public Task<byte[]> GetMapImageAsync(CancellationToken cancellationToken)
    {
        return _httpClient.GetByteArrayAsync("map.img", cancellationToken);
    }

    public Task<string?> TryGetStateAsync(CancellationToken cancellationToken)
    {
        return TryGetStringAsync("state", cancellationToken);
    }

    public Task<string?> TryGetHudMessagesAsync(CancellationToken cancellationToken)
    {
        return TryGetStringAsync("hudmsg", cancellationToken);
    }

    public Task<string?> TryGetGameChatAsync(CancellationToken cancellationToken)
    {
        return TryGetStringAsync("gamechat", cancellationToken);
    }

    private async Task<string?> TryGetStringAsync(string path, CancellationToken cancellationToken)
    {
        try
        {
            using var response = await _httpClient.GetAsync(path, cancellationToken).ConfigureAwait(false);
            if (!response.IsSuccessStatusCode)
            {
                return null;
            }

            return await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
        }
        catch (HttpRequestException)
        {
            return null;
        }
        catch (TaskCanceledException) when (!cancellationToken.IsCancellationRequested)
        {
            return null;
        }
    }

    public void Dispose()
    {
        if (_ownsClient)
        {
            _httpClient.Dispose();
        }
    }
}
