using System.Text.Json; using System.Text.Json.Serialization; using LindtLeerformPlugin.Models; using OpenCvSharp; namespace LindtLeerformPlugin.Services; public class LeerformRecipeStore { private const string RecipeExtension = ".jleerform"; public string RecipesDirectory { get; } = Path.Combine("..", "Data", "Recipes"); private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true, WriteIndented = true, Converters = { new JsonStringEnumConverter() } }; public IReadOnlyList ListRecipeNames() { if (!Directory.Exists(RecipesDirectory)) return Array.Empty(); return Directory.GetFiles(RecipesDirectory, "*" + RecipeExtension) .Select(Path.GetFileNameWithoutExtension) .Where(name => !string.IsNullOrEmpty(name)) .Select(name => name!) .OrderBy(name => name, StringComparer.OrdinalIgnoreCase) .ToList(); } public LeerformRecipe? Load(string recipeName) { if (string.IsNullOrWhiteSpace(recipeName)) return null; var path = GetRecipePath(recipeName); if (!File.Exists(path)) return null; var json = File.ReadAllText(path); return JsonSerializer.Deserialize(json, JsonOptions); } public void Save(LeerformRecipe recipe) { if (string.IsNullOrWhiteSpace(recipe.RecipeName)) throw new ArgumentException("Recipe must have a name", nameof(recipe)); Directory.CreateDirectory(RecipesDirectory); var path = GetRecipePath(recipe.RecipeName); var json = JsonSerializer.Serialize(recipe, JsonOptions); File.WriteAllText(path, json); } public static Mat? DecodeThumbnail(LeerformRecipe recipe) { if (string.IsNullOrEmpty(recipe.ThumbnailBase64)) return null; try { var bytes = Convert.FromBase64String(recipe.ThumbnailBase64); var mat = Cv2.ImDecode(bytes, ImreadModes.Color); return mat.Empty() ? null : mat; } catch { return null; } } private string GetRecipePath(string recipeName) => Path.Combine(RecipesDirectory, recipeName + RecipeExtension); }