flower-story/FlowerApp/Data/FlowerDatabase.cs
2023-08-02 23:45:04 +08:00

240 lines
7.0 KiB
C#

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<FlowerDatabase> logger)
{
Logger = logger;
}
private Dictionary<int, NamedItem>? categories;
private Dictionary<int, EventItem>? events;
public Dictionary<int, NamedItem>? Categories => categories;
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<ParamItem>().FirstOrDefaultAsync(p => p.Code == Constants.LastTokenName);
var token = tk?.Value;
#endif
if (token is string t)
{
Constants.SetAuthorization(t);
var user = await database.Table<UserItem>().FirstOrDefaultAsync(u => u.Token == t);
if (user != null)
{
AppResources.SetUser(user);
}
}
var version = await database.Table<ParamItem>().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<DefinitionItem>();
var defs = new List<DefinitionItem>();
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<DefinitionItem>().ToListAsync();
var cates = new Dictionary<int, NamedItem>();
var evts = new Dictionary<int, EventItem>();
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<int> GetLogCount()
{
await Init();
return await database.Table<LogItem>().Where(l => l.OwnerId < 0 || l.OwnerId == AppResources.User.Id).CountAsync();
}
public async Task<LogItem[]> GetLogs()
{
await Init();
return await database.Table<LogItem>().Where(l => l.OwnerId < 0 || l.OwnerId == AppResources.User.Id).OrderByDescending(l => l.LogUnixTime).ToArrayAsync();
}
public async Task<int> AddLog(LogItem log)
{
await Init();
return await database.InsertAsync(log);
}
public async Task<FlowerItem[]> GetFlowers()
{
await Init();
return await database.Table<FlowerItem>().ToArrayAsync();
}
public async Task<int> UpdateFlowers(IEnumerable<FlowerItem> flowers)
{
await Init();
var ids = flowers.Select(f => f.Id).ToList();
var count = await database.Table<FlowerItem>().DeleteAsync(f => ids.Contains(f.Id));
await database.Table<PhotoItem>().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<int> SetUser(UserItem user)
{
await Init();
var count = user.Id > 0 ?
await database.Table<UserItem>().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<ParamItem>().FirstOrDefaultAsync(p => p.Code == Constants.LastTokenName);
c ??= new ParamItem { Code = Constants.LastTokenName };
c.Value = user.Token;
await database.InsertOrReplaceAsync(c);
}
return count;
}
}