using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using JpnCardsPokemon.Sdk.Api;
using JpnCardsPokemon.Sdk.Utils.QueryFilter;
namespace JpnCardsPokemon.Sdk.Client;
///
/// A client to interact with the web api.
///
public class ApiClient
{
private readonly HttpClient _client;
#if NETCOREAPP3_1_OR_GREATER
///
/// Creates a new instance of the ApiClient.
///
/// Can pass a to use for the internal http client.
public ApiClient(SocketsHttpHandler handler) : this(new HttpClient(handler))
{
}
#endif
///
/// Creates a new instance of the ApiClient.
///
public ApiClient() : this(new HttpClient())
{
}
///
/// Creates a new instance of the ApiClient.
///
/// Can pass a http client to use.
public ApiClient(HttpClient client)
{
_client = client;
_client.BaseAddress = new Uri("https://www.jpn-cards.com/v2/");
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(
new ProductHeaderValue("JpnCardsPokemonSdkCS", GetType().Assembly.GetName().Version?.ToString())));
}
private async Task FetchInternalAsync(string requestUri)
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
IncludeFields = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
return await _client.GetFromJsonAsync(requestUri, options);
}
private string SetQuery(string? filter)
{
return !string.IsNullOrEmpty(filter) ? $"set/{filter.TrimStart('/')}" : "set";
}
///
/// Fetches all .
///
/// Returns an enumerable containing all .
public async Task> FetchSetsAsync()
{
return await FetchInternalAsync>(SetQuery(null)) ?? Enumerable.Empty();
}
///
/// Fetches a by its id.
///
/// Id of the to fetch.
/// If existing returns the matching .
public async Task FetchSetById(int id)
{
return await FetchInternalAsync(SetQuery(id.ToString()));
}
///
/// Fetches a by its uuid.
///
/// Uuid of the to fetch.
/// If existing returns the matching .
public async Task FetchSetByUuid(int uuid)
{
return await FetchInternalAsync(SetQuery($"uuid/{uuid}"));
}
///
/// Fetches from a search query.
///
/// The search query.
/// Returns an enumerable of matching the .
/// Thrown if the is empty.
///
/// At least one filter query must be specified. More information about the query format can be found at
/// https://jpn-cards-site.readthedocs.io/en/latest/api_docs/pokemon/v2/v2_api/#card-queries.
///
public async Task> FetchCardsAsync(string query)
{
if (string.IsNullOrWhiteSpace(query))
throw new Exception("Query string required");
// JSON response is wrapped into a data property, so we parse as JsonDocument first before deserialization.
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
IncludeFields = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var jsonData = await FetchInternalAsync($"card/{query}");
return jsonData?.RootElement.GetProperty("data").Deserialize>(options) ??
Enumerable.Empty();
}
///
/// Fetches from a search query.
///
/// Configured query builder to generate the search query.
/// Returns an enumerable of matching the .
/// At least one filter must be specified.
public async Task?> FetchCardsAsync(IQueryFilterBuilder filterBuilder)
{
return await FetchCardsAsync(filterBuilder.BuildQueryString());
}
}