using System; using System.ComponentModel; using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using DynamicData; using DynamicData.Binding; using Splat; using StarsAssistant.Model; using StarsAssistant.ViewModels; namespace StarsAssistant.Services; public class PlanetManager : IDisposable, IEnableLogger { protected Services.Game Game = Locator.Current.GetService()!; /// /// SourceCache for DynamicData views /// private SourceCache _planets = new(p => p.Name); /// /// Observable changeset showing all player planets converted to view models. /// public IObservable> PlayerPlanetsSource => _planets .Connect() .Filter(planet => planet.OwnerId == Game.Player.Name) .Transform(planet => new PlayerPlanetViewModel(planet)); /// /// Cache with all player planets, indexed by planet name. /// private SourceCache _playerPlanets = new(p => p.Planet.Name); /// /// Observable subject to trigger when we update the planet cache, allows the /// UI to react to it. /// private readonly Subject _planetsReloadedSubject = new(); /// /// Exposes _planetReloadedSubject as IObservable. /// public IObservable PlanetsReloaded => _planetsReloadedSubject.AsObservable(); public PlanetManager() { FleetManager fleetManager = Locator.Current.GetService()!; } /// /// Load the planet records from the database and push them into our source cache. /// public void InitFromDatabase() { using var db = Locator.Current.GetService()!; var allPlanets = db.Planet.ToList(); var cacheKeys = _planets.Keys.ToList(); var planetNames = from p in allPlanets select p.Name; var planetsToDelete = cacheKeys.Except(planetNames); _planets.Edit(innerCache => { foreach (var name in planetsToDelete) innerCache.RemoveKey(name); innerCache.AddOrUpdate(allPlanets); } ); var allPlayerPlanets = allPlanets.Where(planet => planet.OwnerId == Game.Player.Name); var allPlayerCacheKeys = _playerPlanets.Keys.ToList(); var playerPlanetNames = from p in allPlayerPlanets select p.Name; var playerPlanetsToDelete = allPlayerCacheKeys.Except(playerPlanetNames); _playerPlanets.Edit(innerCache => { foreach (var name in playerPlanetsToDelete) innerCache.RemoveKey(name); foreach (var planet in allPlayerPlanets) { var playerPlanet = innerCache.Lookup(planet.Name); if (playerPlanet.HasValue) playerPlanet.Value.Planet = planet; else innerCache.AddOrUpdate(new PlayerPlanetViewModel(planet)); } } ); _planetsReloadedSubject.OnNext(Unit.Default); } /// /// Handle disposal of all subscriptions and dependencies. /// / protected virtual void Dispose(bool disposing) { if (disposing) { _planets.Dispose(); _planetsReloadedSubject.Dispose(); } } /// /// Boilerplate disposal /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }