using System.Collections.ObjectModel; using System.Diagnostics; using System.Windows; using System.Windows.Input; using System.Windows.Threading; using SpdUp.Core; using SpdUp.Models; using SpdUp.Services; namespace SpdUp.ViewModels; /// /// Root ViewModel – drives the main window, navigation, boost, and monitoring. /// public sealed class MainViewModel : ObservableObject, IDisposable { // ── Services ─────────────────────────────────────────────────────── private readonly AppSettings _settings; private readonly OptimizationService _optimizationService; private readonly GameDetectionService _gameDetectionService; private readonly MonitoringService _monitoringService; private readonly NetworkService _networkService = new(); private readonly Dispatcher _dispatcher; // ── Sub-ViewModels ───────────────────────────────────────────────── public DashboardViewModel Dashboard { get; } public BoostViewModel Boost { get; } public MonitorViewModel Monitor { get; } public GameLibraryViewModel GameLibrary { get; } public ProcessManagerViewModel ProcessManager { get; } public ServiceManagerViewModel ServiceManager { get; } public SettingsViewModel Settings { get; } public DebugLogViewModel DebugLog { get; } // ── Navigation ───────────────────────────────────────────────────── private object _currentPage; public object CurrentPage { get => _currentPage; set => SetProperty(ref _currentPage, value); } private string _currentPageTitle = "Dashboard"; public string CurrentPageTitle { get => _currentPageTitle; set => SetProperty(ref _currentPageTitle, value); } // ── Status ───────────────────────────────────────────────────────── private string _statusText = "Ready"; public string StatusText { get => _statusText; set => SetProperty(ref _statusText, value); } private bool _isBoosted; public bool IsBoosted { get => _isBoosted; set => SetProperty(ref _isBoosted, value); } // ── Live Metrics (bound by views & widget) ───────────────────────── private float _cpuUsage; public float CpuUsage { get => _cpuUsage; set => SetProperty(ref _cpuUsage, value); } private float _ramUsagePercent; public float RamUsagePercent { get => _ramUsagePercent; set => SetProperty(ref _ramUsagePercent, value); } private float _ramUsedMB; public float RamUsedMB { get => _ramUsedMB; set => SetProperty(ref _ramUsedMB, value); } private float _ramTotalMB; public float RamTotalMB { get => _ramTotalMB; set => SetProperty(ref _ramTotalMB, value); } private float _gpuUsage; public float GpuUsage { get => _gpuUsage; set => SetProperty(ref _gpuUsage, value); } private float _cpuTemp; public float CpuTemp { get => _cpuTemp; set => SetProperty(ref _cpuTemp, value); } private float _gpuTemp; public float GpuTemp { get => _gpuTemp; set => SetProperty(ref _gpuTemp, value); } private float _pingMs; public float PingMs { get => _pingMs; set => SetProperty(ref _pingMs, value); } // ── Commands ─────────────────────────────────────────────────────── public ICommand NavigateCommand { get; } public ICommand BoostCommand { get; } public ICommand ToggleWidgetCommand { get; } public ICommand CleanRamCommand { get; } public ICommand CleanShaderCacheCommand { get; } // ── Widget ───────────────────────────────────────────────────────── private bool _isWidgetVisible; public bool IsWidgetVisible { get => _isWidgetVisible; set { if (SetProperty(ref _isWidgetVisible, value)) _settings.ShowWidget = value; } } public MainViewModel() { _dispatcher = Dispatcher.CurrentDispatcher; _settings = AppSettings.Load(); // Initialise services _optimizationService = new OptimizationService(_settings); _gameDetectionService = new GameDetectionService(_settings); _monitoringService = new MonitoringService(_settings.PingTarget); // Sub-ViewModels Dashboard = new DashboardViewModel(this); Boost = new BoostViewModel(this, _optimizationService); Monitor = new MonitorViewModel(this); GameLibrary = new GameLibraryViewModel(_settings, _gameDetectionService); ProcessManager = new ProcessManagerViewModel(); ServiceManager = new ServiceManagerViewModel(_settings); Settings = new SettingsViewModel(_settings, this); DebugLog = new DebugLogViewModel(); _currentPage = Dashboard; // Commands NavigateCommand = new RelayCommand(Navigate); BoostCommand = new RelayCommand(async () => await ToggleBoostAsync()); ToggleWidgetCommand = new RelayCommand(() => IsWidgetVisible = !IsWidgetVisible); CleanRamCommand = new RelayCommand(async () => await CleanRamAsync()); CleanShaderCacheCommand = new RelayCommand(async () => await CleanShaderCacheAsync()); // Wire up monitoring _monitoringService.MetricsUpdated += OnMetricsUpdated; _monitoringService.Start(_settings.MonitoringIntervalMs); // Wire up game detection _gameDetectionService.GameStarted += OnGameStarted; _gameDetectionService.GameStopped += OnGameStopped; if (_settings.AutoDetectGames) _gameDetectionService.Start(); // Widget state _isWidgetVisible = _settings.ShowWidget; Logger.PurgeOldLogs(); Logger.Info("Application started."); } // ── Navigation ───────────────────────────────────────────────────── private void Navigate(string? pageName) { (CurrentPage, CurrentPageTitle) = pageName switch { "Dashboard" => ((object)Dashboard, "Dashboard"), "Boost" => (Boost, "Game Boost"), "Monitor" => (Monitor, "System Monitor"), "Games" => (GameLibrary, "Game Library"), "Processes" => (ProcessManager, "Process Manager"), "Services" => (ServiceManager, "Service Manager"), "Settings" => (Settings, "Settings"), "Debug" => (DebugLog, "Debug Log"), _ => (Dashboard, "Dashboard") }; } // ── Boost Toggle ─────────────────────────────────────────────────── private async Task ToggleBoostAsync() { if (_optimizationService.IsBoosted) { StatusText = "Deactivating boost..."; await _optimizationService.DeactivateBoostAsync(); IsBoosted = false; StatusText = "Boost deactivated – settings restored."; } else { StatusText = "Activating boost..."; var gameProcess = _gameDetectionService.CurrentGameProcess; var result = await _optimizationService.ActivateBoostAsync(gameProcess); IsBoosted = result.Success; StatusText = result.Success ? "🚀 Boost Active" : result.Message; } } // ── Quick Actions ────────────────────────────────────────────────── private async Task CleanRamAsync() { StatusText = "Cleaning RAM..."; var result = await Task.Run(() => new RamOptimizationService().FullCleanup()); StatusText = $"RAM cleaned: {result.TrimmedCount} processes trimmed."; } private async Task CleanShaderCacheAsync() { StatusText = "Cleaning shader caches..."; var result = await Task.Run(() => ShaderCacheCleanerService.CleanAll()); StatusText = $"Shader cache: {result.FilesDeleted} files, {result.MBFreed:F1} MB freed."; } // ── Monitoring Callback ──────────────────────────────────────────── private void OnMetricsUpdated(SystemMetrics m) { _dispatcher.BeginInvoke(() => { CpuUsage = m.CpuUsage; RamUsagePercent = m.RamUsagePercent; RamUsedMB = m.RamUsageMB; RamTotalMB = m.RamTotalMB; GpuUsage = m.GpuUsage; CpuTemp = m.CpuTemperature; GpuTemp = m.GpuTemperature; PingMs = m.NetworkPingMs; }); } // ── Game Detection Callbacks ─────────────────────────────────────── #pragma warning disable CS4014 // Fire-and-forget is intentional for event handlers private async void OnGameStarted(string processName) { _dispatcher.BeginInvoke(() => StatusText = $"Game detected: {processName}"); if (_settings.AutoBoostOnGameLaunch && !_optimizationService.IsBoosted) { var result = await _optimizationService.ActivateBoostAsync(processName); _dispatcher.BeginInvoke(() => { IsBoosted = result.Success; StatusText = result.Success ? $"🚀 Auto-Boost for {processName}" : result.Message; }); } } private async void OnGameStopped(string processName) { if (_optimizationService.IsBoosted) { await _optimizationService.DeactivateBoostAsync(); _dispatcher.BeginInvoke(() => { IsBoosted = false; StatusText = $"Game exited: {processName} – boost deactivated."; }); } } #pragma warning restore CS4014 public void SaveSettings() => _settings.Save(); public void Dispose() { _monitoringService.MetricsUpdated -= OnMetricsUpdated; _monitoringService.Dispose(); _gameDetectionService.Dispose(); _settings.Save(); Logger.Info("Application closed."); } }