using Blahblah.FlowerApp.Data.Model; using Microsoft.Extensions.Logging; using SQLite; namespace Blahblah.FlowerApp.Data; public class FlowerDatabase : ILoggerContent { public ILogger Logger { get; } public FlowerDatabase Database => this; private SQLiteAsyncConnection database = null!; public FlowerDatabase(ILogger logger) { Logger = logger; } private Dictionary? categories; private Dictionary? events; public string Category(int categoryId) { if (categories?.TryGetValue(categoryId, out var category) == true) { return category.Name; } return Constants.CategoryOther; } public string Event(int eventId) { if (events?.TryGetValue(eventId, out var @event) == true) { return @event.Name; } return Constants.EventUnknown; } private async Task Init() { if (database is not null) { return; } #if DEBUG Logger.LogInformation("database path: {path}", Constants.DatabasePath); #endif database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.SQLiteFlags); #if DEBUG1 var result = #endif await database.CreateTablesAsync(CreateFlags.None, typeof(FlowerItem), typeof(RecordItem), typeof(PhotoItem), typeof(UserItem), typeof(DefinitionItem), typeof(ParamItem), typeof(LogItem)); #if DEBUG1 foreach (var item in result.Results) { this.LogInformation($"create table {item.Key}, result: {item.Value}"); } #endif } public async Task Setup() { await Init(); #if DEBUG1 var token = "RF4mfoUur0vHtWzHwD42ka0FhIfGaPnBxoQgrXOYEDg="; #else var tk = await database.Table().FirstOrDefaultAsync(p => p.Code == Constants.LastTokenName); var token = tk?.Value; #endif if (token is string t) { Constants.SetAuthorization(t); var user = await database.Table().FirstOrDefaultAsync(u => u.Token == t); if (user != null) { AppResources.SetUser(user); } } var version = await database.Table().FirstOrDefaultAsync(p => p.Code == Constants.ApiVersionName); var definition = await Constants.Initialize(this, version?.Value); if (definition != null) { categories = definition.Categories; events = definition.Events; this.LogInformation($"new version founded, from ({version?.Value}) to ({definition.ApiVersion})"); if (version == null) { version = new ParamItem { Code = Constants.ApiVersionName, Value = definition.ApiVersion }; } else { version.Value = definition.ApiVersion; } await database.InsertOrReplaceAsync(version); // replace local definitions await database.DeleteAllAsync(); var defs = new List(); foreach (var category in definition.Categories) { defs.Add(new DefinitionItem { DefinitionType = 0, DefinitionId = category.Key, Name = category.Value.Name, Description = category.Value.Description }); } foreach (var @event in definition.Events) { defs.Add(new DefinitionItem { DefinitionType = 1, DefinitionId = @event.Key, Name = @event.Value.Name, Description = @event.Value.Description, Unique = @event.Value.Unique }); } var rows = await database.InsertAllAsync(defs); this.LogInformation($"{defs.Count} definitions, {rows} rows inserted"); } else { // use local definitions var defs = await database.Table().ToListAsync(); var cates = new Dictionary(); var evts = new Dictionary(); foreach (var d in defs) { if (d.DefinitionType == 0) { // category cates[d.DefinitionId] = new NamedItem(d.Name, d.Description); } else if (d.DefinitionType == 1) { // event evts[d.DefinitionId] = new EventItem(d.Name, d.Description, d.Unique ?? false); } } categories = cates; events = evts; } } public async Task AddLog(LogItem log) { await Init(); return await database.InsertAsync(log); } public async Task GetFlowers() { await Init(); return await database.Table().ToArrayAsync(); } public async Task UpdateFlowers(IEnumerable flowers) { await Init(); var ids = flowers.Select(f => f.Id).ToList(); var count = await database.Table().DeleteAsync(f => ids.Contains(f.Id)); await database.Table().DeleteAsync(p => p.RecordId == null && ids.Contains(p.FlowerId)); await database.InsertAllAsync(flowers); foreach (var flower in flowers) { if (flower.Photos?.Length > 0) { await database.InsertAllAsync(flower.Photos); } } return count; } public async Task SetUser(UserItem user) { await Init(); var count = user.Id > 0 ? await database.Table().CountAsync(u => u.Id == user.Id) : 0; if (count > 0) { count = await database.UpdateAsync(user); } else { count = await database.InsertAsync(user); } if (count > 0) { var c = await database.Table().FirstOrDefaultAsync(p => p.Code == Constants.LastTokenName); c ??= new ParamItem { Code = Constants.LastTokenName }; c.Value = user.Token; await database.InsertOrReplaceAsync(c); } return count; } }