using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using InABox.Clients; namespace InABox.Core { public interface IDigitalFormDocumentHandler { Task LoadDocumentAsync(Guid id); byte[] LoadDocument(Guid id); Guid SaveDocument(byte[] data); void Run(); void Stop(); } public abstract class DigitalFormDocumentHandler : IDigitalFormDocumentHandler { private static String FileName(Guid id) => $"{id}.formdocument"; protected abstract String CachePath { get; } protected abstract bool IsConnected { get; } private static Action? _status; public byte[] LoadDocument(Guid id) { var fullpath = Path.Combine(CachePath, FileName(id)); if (File.Exists(fullpath)) return File.ReadAllBytes(fullpath); var result = new Client().Query( new Filter(x => x.FileName).IsEqualTo(FileName(id)), null, null ).Rows.FirstOrDefault()?.Get(c=>c.Data); return result; } public async Task LoadDocumentAsync(Guid id) { var fullpath = Path.Combine(CachePath, FileName(id)); if (File.Exists(fullpath)) return File.ReadAllBytes(fullpath); else { var data = await Client.QueryAsync( new Filter(x => x.FileName).IsEqualTo(FileName(id)), Columns.None().Add(x => x.Data), null, CoreRange.All); return data.Rows.FirstOrDefault().Get(x => x.Data); } } public Guid SaveDocument(byte[] data) { Guid result = Guid.NewGuid(); var filename = Path.Combine(CachePath, FileName(result)); File.WriteAllBytes(filename,data); return result; } private CancellationTokenSource? _cancel; public void Stop() { if (_cancel != null) { _cancel.Cancel(); _cancel = null; } } protected DigitalFormDocumentHandler(Action status) { _status = status; } public void Run() { Stop(); _cancel = new CancellationTokenSource(); Task.Run( () => { bool? previouslyActive = null; while (_cancel?.IsCancellationRequested != true) { var file = Directory.EnumerateFiles(CachePath, "*.formdocument") .FirstOrDefault(); var isActive = !String.IsNullOrWhiteSpace(file); if (isActive != previouslyActive) { previouslyActive = isActive; _status?.Invoke(isActive); } if (!String.IsNullOrWhiteSpace(file) && File.Exists(file) && IsConnected) { var data = File.ReadAllBytes(file); var document = new Document() { FileName = Path.GetFileName(file), Data = data, CRC = CoreUtils.CalculateCRC(data), TimeStamp = DateTime.Now, Created = DateTime.Now, CreatedBy = ClientFactory.UserID }; new Client().Save(document, "Uploaded from Mobile Device"); File.Delete(file); } Thread.Sleep(1000); } }, _cancel.Token ); } } public static class DigitalFormDocumentFactory { private static IDigitalFormDocumentHandler? _handler; public static void Init(THandler handler) where THandler : IDigitalFormDocumentHandler { _handler = handler; } public static IDigitalFormDocumentHandler Handler => _handler ?? throw new Exception("Digital form document handler uninitialised."); public static void Run() => _handler?.Run(); public static void Stop() => _handler?.Stop(); public static void LoadDocument(Guid id, Action callback) => LoadDocumentAsync(id).ContinueWith(task => callback(task.Result), TaskScheduler.FromCurrentSynchronizationContext()); public static Task LoadDocumentAsync(Guid id) => Handler.LoadDocumentAsync(id); public static byte[]? LoadDocument(Guid id) => Handler.LoadDocument(id); public static Guid SaveDocument(byte[] data) => Handler.SaveDocument(data); } }