using System; using System.Threading.Tasks; using Flawless.Client.Remote; using ReactiveUI; using Refit; namespace Flawless.Client.Service; public class Api { #region Instance private static Api? _instance; public static Api Current => _instance ??= new Api(); #endregion public IObservable IsLoggedIn => _isLoggedIn; public IObservable ServerUrl => _serverUrl; public IObservable Status => _status; public IObservable Token => _token; private readonly ReactiveProperty _isLoggedIn = new(false); private readonly ReactiveProperty _serverUrl = new(string.Empty); private readonly ReactiveProperty _status = new(null); private readonly ReactiveProperty _token = new(null); #region GatewayConfig private IFlawlessServer? _gateway; public bool IsGatewayReady => _gateway != null; public IFlawlessServer Gateway => _gateway ?? throw new InvalidProgramException("Not set gateway yet!"); public void ClearGateway() { _gateway = null; _isLoggedIn.Value = false; _status.Value = null; _serverUrl.Value = null; _token.Value = null; } public async Task SetGatewayAsync(string host) { var setting = new RefitSettings { AuthorizationHeaderValueGetter = (req, ct) => _token.Value != null ? Task.FromResult($"Bearer {_token}") : Task.FromResult(string.Empty) }; var tempGateway = RestService.For(host, setting); _status.Value = await tempGateway.Status(); _serverUrl.Value = host; _gateway = tempGateway; } public async ValueTask LoginAsync(string username, string password) { _token.Value = await _gateway.Login(new LoginRequest { Username = username, Password = password }); _isLoggedIn.Value = true; } #endregion #region TokenOperations public bool RequireRefreshToken() { if (_token.Value == null) return true; if (DateTime.UtcNow.AddMinutes(1) > _token.Value.Expiration) return true; return false; } public async ValueTask TryRefreshTokenAsync() { if (_token.Value == null) return false; try { _token.Value = await Gateway.Refresh(_token.Value); } catch (Exception e) { await Console.Error.WriteLineAsync(e.ToString()); return false; } return true; } #endregion }