using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace ExtensiblePortfolioSite.SDK
{
    /// <summary>
    /// Provides a simple Async HTTP Client
    /// </summary>
    public static class HTTP
    {
        private static readonly HttpClient Client = new();


        ///
        public static Stream GetStream(Uri URL) => Client.GetStreamAsync(URL).ConfigureAwait(false).GetAwaiter().GetResult();
        ///
        public static async Task<Stream> GetStreamAsync(Uri URL) => await Client.GetStreamAsync(URL);
        ///
        public static async Task<Stream> GetStreamAsync(Uri URL, CancellationToken cancellationToken = default) => await Client.GetStreamAsync(URL, cancellationToken);


        ///
        public static HttpResponseMessage Post(Uri URL, HttpContent content) => Client.PostAsync(URL, content).ConfigureAwait(false).GetAwaiter().GetResult();
        ///
        public static async Task<HttpResponseMessage> PostAsync(Uri URL, HttpContent content) => await Client.PostAsync(URL, content);
        ///
        public static async Task<HttpResponseMessage> PostAsync(Uri URL, HttpContent content, CancellationToken cancellationToken = default) => await Client.PostAsync(URL, content, cancellationToken);


        ///
        public static String GetString(Uri URL) => Client.GetStringAsync(URL).ConfigureAwait(false).GetAwaiter().GetResult();
        ///
        public static async Task<String> GetStringAsync(Uri URL) => await Client.GetStringAsync(URL);
        ///
        public static async Task<String> GetStringAsync(Uri URL, CancellationToken cancellationToken = default) => await Client.GetStringAsync(URL, cancellationToken);


        ///
        public static T? GetArtifact<T>(Uri URL)
        {
            using Stream stm = GetStream(URL);
            return JsonSerializer.Deserialize<T>(stm);
        }
        ///
        public static async ValueTask<T?> GetArtifactAsync<T>(Uri URL)
        {
            using Stream stm = await GetStreamAsync(URL);
            return await JsonSerializer.DeserializeAsync<T>(stm);
        }
        ///
        public static async ValueTask<T?> GetArtifactAsync<T>(Uri URL, CancellationToken cancellationToken = default)
        {
            using Stream stm = await GetStreamAsync(URL, cancellationToken);
            return await JsonSerializer.DeserializeAsync<T>(stm, cancellationToken: cancellationToken);
        }
        

        ///
        public static HttpResponseMessage PostArtifact<T>(Uri URL, T Obj) => Client.PostAsJsonAsync<T>(URL, Obj).ConfigureAwait(false).GetAwaiter().GetResult();
        ///
        public static async Task<HttpResponseMessage> PostArtifactAsync<T>(Uri URL, T Obj) => await Client.PostAsJsonAsync<T>(URL, Obj);
        ///
        public static async Task<HttpResponseMessage> PostArtifactAsync<T>(Uri URL, T Obj, CancellationToken cancellationToken = default) => await Client.PostAsJsonAsync<T>(URL, Obj, cancellationToken);
    }
}
