using System;
using System.IO;
using System.Reactive.Linq;
using System.Text.RegularExpressions;
using ReactiveUI;
using Splat;
using StarsAssistant.Helpers;
namespace StarsAssistant.Services;
public partial class CSVDataLoader : IEnableLogger
{
///
/// Reference to the game metadata, retrieved by DI
///
protected Services.Game Game = Locator.Current.GetService()!;
///
/// Regex to match fs watcher results to Stars file types.
///
/// Precompiled RegEx
[GeneratedRegex(@".*\.(?[pf])(?\d)+$")]
private static partial Regex MyRegex();
///
/// RegEx Instance to match Stars file types.
///
protected Regex FileTypeRegEx = MyRegex();
///
/// Instance of the FSWatcher, to which we subscribe.
///
protected IObservable Watcher;
///
/// Active subscription to FsWatcher.
///
protected IDisposable? Subscription;
///
/// Construct the instance and prepare our FS Watcher.
///
public CSVDataLoader()
{
// string[] filters = { "*.p*", "*.f*", "*.map" };
Watcher = FsWatcher
.ObserveFileSystem(Game.GamePath, [ Game.PlanetFileSearchPattern, Game.FleetFileSearchPattern ])
.ThrottleAndDistinct(2, RxApp.TaskpoolScheduler)
.Log(this, $"{DateTime.Now.ToLongTimeString()} FsEvent", fsEvent => $"{fsEvent.FullPath} {fsEvent.ChangeType}")
.ObserveOn(RxApp.TaskpoolScheduler);
}
///
/// Start the CSV watcher, and capture our disposable, so that we can shut
/// down the watcher if needed.
///
public void StartCSVWatcher()
{
if (Subscription != null)
throw new InvalidOperationException("CSV Watcher is active, can't start it again.");
Subscription = Watcher.Subscribe(fsEvent => this.LoadFile(fsEvent.FullPath));
}
///
/// Subscription to File Processing, called by our subscription to the watcher.
///
/// The File to process
protected void LoadFile(string fileName)
{
Match m = FileTypeRegEx.Match(fileName);
if (! m.Success)
{
this.Log().Error($"Failed to parse {fileName} to identify what we are looking at. Ignoring file.");
return;
}
string type = m.Groups["type"].Value;
string player = m.Groups["player"].Value;
this.Log().Debug($"Got file type {type} for player {player}");
switch (type)
{
case "p":
var planetLoader = new CSV.PlanetLoader();
planetLoader.ImportForRace(Services.Game.Player);
PlanetManager planetManager = Locator.Current.GetService()!;
planetManager.InitFromDatabase();
break;
case "f":
var fleetLoader = new CSV.FleetLoader();
fleetLoader.ImportForRace(Services.Game.Player);
FleetManager fleetManager = Locator.Current.GetService()!;
FleetManager.PostProcessImportedData();
fleetManager.InitFromDatabase();
break;
default:
this.Log().Warn($"Planet loader got unknown file type ${type}. Ignoring file.");
break;
}
}
}