using System.IO; using System.Linq; using System.Threading.Tasks; using SQLite; using Wino.Core.Domain.Entities.Calendar; using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Interfaces; namespace Wino.Services; public interface IDatabaseService : IInitializeAsync { SQLiteAsyncConnection Connection { get; } } public class DatabaseService : IDatabaseService { private const string DatabaseName = "Wino180.db"; private bool _isInitialized = false; private readonly IApplicationConfiguration _folderConfiguration; public SQLiteAsyncConnection Connection { get; private set; } public DatabaseService(IApplicationConfiguration folderConfiguration) { _folderConfiguration = folderConfiguration; } public async Task InitializeAsync() { if (_isInitialized) return; var publisherCacheFolder = _folderConfiguration.PublisherSharedFolderPath; var databaseFileName = Path.Combine(publisherCacheFolder, DatabaseName); Connection = new SQLiteAsyncConnection(databaseFileName); await CreateTablesAsync(); _isInitialized = true; } private async Task CreateTablesAsync() { await Task.WhenAll( Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync(), Connection.CreateTableAsync() ); await EnsureSchemaUpgradesAsync().ConfigureAwait(false); } private async Task EnsureSchemaUpgradesAsync() { var folderColumns = await Connection.GetTableInfoAsync(nameof(MailItemFolder)).ConfigureAwait(false); if (!folderColumns.Any(c => c.Name == nameof(MailItemFolder.HighestKnownUid))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(MailItemFolder)} ADD COLUMN {nameof(MailItemFolder.HighestKnownUid)} INTEGER NOT NULL DEFAULT 0") .ConfigureAwait(false); } if (!folderColumns.Any(c => c.Name == nameof(MailItemFolder.LastUidReconcileUtc))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(MailItemFolder)} ADD COLUMN {nameof(MailItemFolder.LastUidReconcileUtc)} TEXT NULL") .ConfigureAwait(false); } var customServerColumns = await Connection.GetTableInfoAsync(nameof(CustomServerInformation)).ConfigureAwait(false); if (!customServerColumns.Any(c => c.Name == nameof(CustomServerInformation.CalDavServiceUrl))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(CustomServerInformation)} ADD COLUMN {nameof(CustomServerInformation.CalDavServiceUrl)} TEXT NULL") .ConfigureAwait(false); } if (!customServerColumns.Any(c => c.Name == nameof(CustomServerInformation.CalDavUsername))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(CustomServerInformation)} ADD COLUMN {nameof(CustomServerInformation.CalDavUsername)} TEXT NULL") .ConfigureAwait(false); } if (!customServerColumns.Any(c => c.Name == nameof(CustomServerInformation.CalDavPassword))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(CustomServerInformation)} ADD COLUMN {nameof(CustomServerInformation.CalDavPassword)} TEXT NULL") .ConfigureAwait(false); } if (!customServerColumns.Any(c => c.Name == nameof(CustomServerInformation.CalendarSupportMode))) { await Connection .ExecuteAsync($"ALTER TABLE {nameof(CustomServerInformation)} ADD COLUMN {nameof(CustomServerInformation.CalendarSupportMode)} INTEGER NOT NULL DEFAULT 0") .ConfigureAwait(false); } } }