using Microsoft.EntityFrameworkCore; using RadicadeServer.DB; using RadicadeServer.RecNet.Config; using System.Text.Json; namespace RadicadeServer.API.Rooms.V1; internal sealed class RoomAssetRecord { public string Id { get; set; } = ""; public long RoomId { get; set; } public string Kind { get; set; } = ""; public Dictionary Fields { get; set; } = new(StringComparer.OrdinalIgnoreCase); } internal static class RoomAssetStore { private const string ConfigKey = "RoomAssets"; private static readonly SemaphoreSlim Gate = new(1, 1); public static async Task> LoadAsync(RecDBContext db) { var config = await db.ServerConfig.AsNoTracking().FirstOrDefaultAsync(row => row.Key == ConfigKey); if (string.IsNullOrWhiteSpace(config?.Value)) return new List(); try { return JsonSerializer.Deserialize>(config.Value, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new List(); } catch (JsonException) { return new List(); } } public static async Task> ForRoomAsync(RecDBContext db, long roomId, string kind) { var records = await LoadAsync(db); return records.Where(record => record.RoomId == roomId && string.Equals(record.Kind, kind, StringComparison.OrdinalIgnoreCase)).ToList(); } public static async Task SaveAsync(RecDBContext db, RoomAssetRecord record) { await Gate.WaitAsync(); try { var config = await db.ServerConfig.FirstOrDefaultAsync(row => row.Key == ConfigKey); List records; try { records = string.IsNullOrWhiteSpace(config?.Value) ? new List() : JsonSerializer.Deserialize>(config.Value, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new List(); } catch (JsonException) { records = new List(); } records.RemoveAll(existing => existing.RoomId == record.RoomId && string.Equals(existing.Kind, record.Kind, StringComparison.OrdinalIgnoreCase) && existing.Id == record.Id); records.Add(record); if (config == null) { config = new ServerConfigVal(ConfigKey, JsonSerializer.Serialize(records)); await db.ServerConfig.AddAsync(config); } else { config.Value = JsonSerializer.Serialize(records); } await db.SaveChangesAsync(); } finally { Gate.Release(); } } public static async Task>> GetDtosAsync(RecDBContext db, long roomId, string kind) { var records = await ForRoomAsync(db, roomId, kind); return records.Select(record => { var dto = new Dictionary(record.Fields, StringComparer.OrdinalIgnoreCase); dto[kind.Equals("currency", StringComparison.OrdinalIgnoreCase) ? "CurrencyId" : "ConsumableId"] = record.Id; dto["RoomId"] = record.RoomId; return dto; }).ToList(); } }