sa/Stars Assistant/Services/PlanetManager.cs

115 lines
3.8 KiB
C#

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<Services.Game>()!;
/// <summary>
/// SourceCache for DynamicData views
/// </summary>
private SourceCache<Planet, string> _planets = new(p => p.Name);
/// <summary>
/// Observable changeset showing all player planets converted to view models.
/// </summary>
public IObservable<IChangeSet<PlayerPlanetViewModel, string>> PlayerPlanetsSource
=> _playerPlanets.AsObservableCache().Connect();
/// <summary>
/// Cache with all player planets, indexed by planet name.
/// </summary>
private SourceCache<PlayerPlanetViewModel, string> _playerPlanets = new(p => p.Planet.Name);
/// <summary>
/// Observable subject to trigger when we update the planet cache, allows the
/// UI to react to it.
/// </summary>
private readonly Subject<Unit> _planetsReloadedSubject = new();
/// <summary>
/// Exposes _planetReloadedSubject as IObservable.
/// </summary>
public IObservable<Unit> PlanetsReloaded => _planetsReloadedSubject.AsObservable();
public PlanetManager()
{
FleetManager fleetManager = Locator.Current.GetService<FleetManager>()!;
}
/// <summary>
/// Load the planet records from the database and push them into our source cache.
/// </summary>
public void InitFromDatabase()
{
using var db = Locator.Current.GetService<StarsDatabase>()!;
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 =>
{
// TODO: Update Planet loop in the same way as the player planet update loop
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);
}
/// <summary>
/// Handle disposal of all subscriptions and dependencies.
/// </summary>/
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_planets.Dispose();
_planetsReloadedSubject.Dispose();
}
}
/// <summary>
/// Boilerplate disposal
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}