using System.Net.Http;
using Mlaumcherb.Client.Avalonia.холопы;

namespace Mlaumcherb.Client.Avalonia.сеть;

public static class NetworkHelper
{
    private static HttpClient _http = new();

    static NetworkHelper()
    {
        // thanks for Sashok :3
        // https://github.com/new-sashok724/Launcher/blob/23485c3f7de6620d2c6b7b2dd9339c3beb6a0366/Launcher/source/helper/IOHelper.java#L259
        _http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
    }

    public static Task<string> GetString(string url, CancellationToken ct = default) => _http.GetStringAsync(url, ct);
    public static Task<Stream> GetStream(string url, CancellationToken ct = default) => _http.GetStreamAsync(url, ct);
    
    public static async Task DownloadFile(string url, Stream outStream, CancellationToken ct = default, 
        params TransformStream.TransformFuncDelegate[] transforms)
    {
        await using var pipe = new TransformStream(await GetStream(url, ct));
        if (transforms.Length > 0) 
            pipe.AddTransforms(transforms);
        await pipe.CopyToAsync(outStream, ct);
    }
    
    public static async Task DownloadFile(string url, IOPath outPath, CancellationToken ct = default, 
        params TransformStream.TransformFuncDelegate[] transforms)
    {
        await using var file = File.OpenWrite(outPath);
        await DownloadFile(url, file, ct, transforms);
    }
    
    public static async Task<T> DownloadStringAndDeserialize<T>(string url)
    {
        var text = await GetString(url);
        var result = JsonConvert.DeserializeObject<T>(text)
            ?? throw new Exception($"can't deserialize {typeof(T).Name}");
        return result;
    }
    
    
    /// <returns>(file_content, didDownload)</returns>
    public static async Task<(string, bool)> ReadOrDownload(IOPath filePath, string url, 
        string? sha1, bool checkHashes)
    {
        if (HashHelper.CheckFileSHA1(filePath, sha1, checkHashes)) 
            return (File.ReadAllText(filePath), false);
        
        string txt = await NetworkHelper.GetString(url);
        File.WriteAllText(filePath, txt);
        return (txt, true);
    }

    /// <returns>(file_content, didDownload)</returns>
    public static async Task<(T, bool)> ReadOrDownloadAndDeserialize<T>(IOPath filePath, string url,
        string? sha1, bool checkHashes)
    {
        (string text, bool didDownload) = await ReadOrDownload(filePath, url, sha1, checkHashes);
        var result = JsonConvert.DeserializeObject<T>(text)
                     ?? throw new Exception($"can't deserialize {typeof(T).Name}");
        return (result, didDownload);
    }
}