using System.Text.Json;
using AIStudio.Provider;
using Microsoft.JSInterop;
// ReSharper disable NotAccessedPositionalProperty.Local
namespace AIStudio.Settings;
///
/// The settings manager.
///
public sealed class SettingsManager
{
private const string SETTINGS_FILENAME = "settings.json";
///
/// The directory where the configuration files are stored.
///
public static string? ConfigDirectory { get; set; }
///
/// The directory where the data files are stored.
///
public static string? DataDirectory { get; set; }
///
/// The configuration data.
///
public Data ConfigurationData { get; private set; } = new();
private bool IsSetUp => !string.IsNullOrWhiteSpace(ConfigDirectory) && !string.IsNullOrWhiteSpace(DataDirectory);
#region API Key Handling
private readonly record struct GetSecretRequest(string Destination, string UserName);
///
/// Data structure for any requested secret.
///
/// True, when the secret was successfully retrieved.
/// The secret, e.g., API key.
/// The issue, when the secret could not be retrieved.
public readonly record struct RequestedSecret(bool Success, string Secret, string Issue);
///
/// Try to get the API key for the given provider.
///
/// The JS runtime to access the Rust code.
/// The provider to get the API key for.
/// The requested secret.
public async Task GetAPIKey(IJSRuntime jsRuntime, IProvider provider) => await jsRuntime.InvokeAsync("window.__TAURI__.invoke", "get_secret", new GetSecretRequest($"provider::{provider.Id}::{provider.InstanceName}::api_key", Environment.UserName));
private readonly record struct StoreSecretRequest(string Destination, string UserName, string Secret);
///
/// Data structure for storing a secret response.
///
/// True, when the secret was successfully stored.
/// The issue, when the secret could not be stored.
public readonly record struct StoreSecretResponse(bool Success, string Issue);
///
/// Try to store the API key for the given provider.
///
/// The JS runtime to access the Rust code.
/// The provider to store the API key for.
/// The API key to store.
/// The store secret response.
public async Task SetAPIKey(IJSRuntime jsRuntime, IProvider provider, string key) => await jsRuntime.InvokeAsync("window.__TAURI__.invoke", "store_secret", new StoreSecretRequest($"provider::{provider.Id}::{provider.InstanceName}::api_key", Environment.UserName, key));
private readonly record struct DeleteSecretRequest(string Destination, string UserName);
///
/// Data structure for deleting a secret response.
///
/// True, when the secret was successfully deleted.
/// The issue, when the secret could not be deleted.
public readonly record struct DeleteSecretResponse(bool Success, string Issue);
///
/// Tries to delete the API key for the given provider.
///
/// The JS runtime to access the Rust code.
/// The provider to delete the API key for.
/// The delete secret response.
public async Task DeleteAPIKey(IJSRuntime jsRuntime, IProvider provider) => await jsRuntime.InvokeAsync("window.__TAURI__.invoke", "delete_secret", new DeleteSecretRequest($"provider::{provider.Id}::{provider.InstanceName}::api_key", Environment.UserName));
#endregion
///
/// Loads the settings from the file system.
///
public async Task LoadSettings()
{
if(!this.IsSetUp)
return;
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
if(!File.Exists(settingsPath))
return;
var settingsJson = await File.ReadAllTextAsync(settingsPath);
var loadedConfiguration = JsonSerializer.Deserialize(settingsJson);
if(loadedConfiguration is null)
return;
this.ConfigurationData = loadedConfiguration;
}
///
/// Stores the settings to the file system.
///
public async Task StoreSettings()
{
if(!this.IsSetUp)
return;
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
if(!Directory.Exists(ConfigDirectory))
Directory.CreateDirectory(ConfigDirectory!);
var settingsJson = JsonSerializer.Serialize(this.ConfigurationData);
await File.WriteAllTextAsync(settingsPath, settingsJson);
}
}