using InABox.Clients; using InABox.Core; namespace InABox.Avalonia; public class QueueUpdaterState { public Guid ID { get; set; } public string OriginalState { get; set; } public Dictionary Changes { get; set; } = new(); public bool DisableUpdates { get; set; } } public class QueueUpdater : IDisposable, IQueueUpdater where TEntity : Entity, IPersistent, IRemotable, new() { private static String StateFile(Guid id) => $"{id}.{typeof(TEntity).Name.Split('.').Last()}"; private Dictionary _cache = new(); private string _path; private IModelHost _host; public QueueUpdater(IModelHost host, string path) { _host = host; _path = path; LoadCache(); _host.AddUpdateQueue(this); } public void Add(TEntity entity) { var _state = new QueueUpdaterState(); _state.ID = Guid.NewGuid(); _state.OriginalState = Serialization.Serialize(entity); Save(_state); _cache[entity] = _state; entity.PropertyChanged += (sender, args) => { var state = _cache[entity]; state.Changes[args.PropertyName] = CoreUtils.GetPropertyValue(entity,args.PropertyName); Save(state); }; } public void Update(TEntity entity, Action action) { var state = _cache[entity]; state.DisableUpdates = true; action(entity); Save(state); state.DisableUpdates = false; } private void Save(QueueUpdaterState state) { var _text = Serialization.Serialize(state); File.WriteAllText(StateFile(state.ID), _text); } public TEntity[] Items => _cache.Keys.ToArray(); private void LoadCache() { _cache.Clear(); var files = Directory.GetFiles(_path, $"*.{typeof(TEntity).Name.Split('.').Last()}"); foreach (var file in files) { if (!Guid.TryParse(Path.GetFileNameWithoutExtension(file), out Guid id)) continue; var _text = File.ReadAllText(file); if (string.IsNullOrWhiteSpace(_text)) continue; var _state = Serialization.Deserialize(_text); if (_state == null) continue; var _entity = Serialization.Deserialize(_state.OriginalState); if (_entity == null) continue; foreach (var change in _state.Changes) CoreUtils.SetPropertyValue(_entity,change.Key,change.Value); _cache[_entity] = _state; } } public void ProcessQueue() { var item = Items.FirstOrDefault(); if (item != null) { if (item.IsChanged() && _host.Status == ConnectionStatus.Connected) { new Client().Save(item, "Updated from Mobile Device"); var state = Serialization.Serialize(item); File.WriteAllText(StateFile(_cache[item].ID),state); } } } public void Dispose() { _host.RemoveUpdateQueue(this); } }