using System; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using LANCommander.Launcher.Services; using LANCommander.Launcher.Settings; using LANCommander.SDK.Models; using LANCommander.SDK.Providers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace LANCommander.Launcher.ViewModels; public partial class SettingsViewModel : ViewModelBase { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; private readonly INavigationService _navigationService; // Game Settings [ObservableProperty] private ObservableCollection _installDirectories = new(); [ObservableProperty] private int _maxInstallAttempts = 10; // Media Settings [ObservableProperty] private string _mediaStoragePath = string.Empty; // UI Settings [ObservableProperty] private CultureItem? _selectedCultureItem; [ObservableProperty] private ObservableCollection _availableCultures = new(); // Notification Settings [ObservableProperty] private bool _notifyOnInstallComplete = true; [ObservableProperty] private bool _notifyOnInstallFailed = true; [ObservableProperty] private bool _notifyOnChatMessage = true; [ObservableProperty] private NotificationSoundTheme _selectedSoundTheme = NotificationSoundTheme.SystemDefault; [ObservableProperty] private ObservableCollection _availableSoundThemes = new(); // Debug Settings [ObservableProperty] private bool _enableScriptDebugging; [ObservableProperty] private string _loggingPath = string.Empty; [ObservableProperty] private LogLevel _selectedLogLevel = LogLevel.Warning; [ObservableProperty] private ObservableCollection _availableLogLevels = new(); [ObservableProperty] private string? _statusMessage; [ObservableProperty] private bool _isSaving; public event EventHandler? SettingsSaved; public SettingsViewModel(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _logger = serviceProvider.GetRequiredService>(); _navigationService = serviceProvider.GetRequiredService(); // Initialize available cultures var cultures = new[] { "en-US", "de", "es", "fr", "it", "pt-BR", "nl", "ja", "zh", "ko", "uk" }; foreach (var code in cultures) { try { var culture = CultureInfo.GetCultureInfo(code); AvailableCultures.Add(new CultureItem(code, culture.NativeName)); } catch { AvailableCultures.Add(new CultureItem(code, code)); } } // Initialize sound themes foreach (var theme in Enum.GetValues()) AvailableSoundThemes.Add(theme); // Initialize log levels foreach (var level in Enum.GetValues()) AvailableLogLevels.Add(level); } public void Load() { _logger.LogInformation("Loading settings..."); using var scope = _serviceProvider.CreateScope(); var settingsProvider = scope.ServiceProvider.GetRequiredService>(); var settings = settingsProvider.CurrentValue; // Game settings InstallDirectories.Clear(); if (settings.Games.InstallDirectories?.Length > 0) foreach (var dir in settings.Games.InstallDirectories) InstallDirectories.Add(new InstallDirectoryItem(dir)); else InstallDirectories.Add(new InstallDirectoryItem(string.Empty)); MaxInstallAttempts = settings.Games.MaxInstallAttempts; // Media settings MediaStoragePath = settings.Media.StoragePath ?? string.Empty; // UI settings var cultureCode = settings.Culture ?? "en-US"; SelectedCultureItem = AvailableCultures.FirstOrDefault(c => c.Code == cultureCode) ?? AvailableCultures.First(); // Notification settings NotifyOnInstallComplete = settings.Notifications.NotifyOnInstallComplete; NotifyOnInstallFailed = settings.Notifications.NotifyOnInstallFailed; NotifyOnChatMessage = settings.Notifications.NotifyOnChatMessage; SelectedSoundTheme = settings.Notifications.SoundTheme; // Debug settings EnableScriptDebugging = settings.Debug.EnableScriptDebugging; LoggingPath = settings.Debug.LoggingPath ?? "Logs"; SelectedLogLevel = settings.Debug.LogLevel; StatusMessage = null; _logger.LogInformation("Settings loaded"); } [RelayCommand] private async Task SaveAsync() { if (IsSaving) return; IsSaving = true; StatusMessage = "Saving..."; try { using var scope = _serviceProvider.CreateScope(); var settingsProvider = scope.ServiceProvider.GetRequiredService>(); settingsProvider.Update(s => { // Game settings s.Games.InstallDirectories = InstallDirectories .Where(d => !string.IsNullOrWhiteSpace(d.Path)) .Select(d => d.Path) .ToArray(); s.Games.MaxInstallAttempts = Math.Max(1, MaxInstallAttempts); // Media settings s.Media.StoragePath = MediaStoragePath; // UI settings s.Culture = SelectedCultureItem?.Code ?? "en-US"; // Notification settings s.Notifications.NotifyOnInstallComplete = NotifyOnInstallComplete; s.Notifications.NotifyOnInstallFailed = NotifyOnInstallFailed; s.Notifications.NotifyOnChatMessage = NotifyOnChatMessage; s.Notifications.SoundTheme = SelectedSoundTheme; // Debug settings s.Debug.EnableScriptDebugging = EnableScriptDebugging; s.Debug.LoggingPath = LoggingPath; s.Debug.LogLevel = SelectedLogLevel; }); StatusMessage = "Settings saved!"; _logger.LogInformation("Settings saved successfully"); SettingsSaved?.Invoke(this, EventArgs.Empty); } catch (Exception ex) { _logger.LogError(ex, "Failed to save settings"); StatusMessage = $"Failed to save: {ex.Message}"; } finally { IsSaving = false; } } [RelayCommand] private void AddInstallDirectory() { InstallDirectories.Add(new InstallDirectoryItem(string.Empty)); } [RelayCommand] private void RemoveInstallDirectory(InstallDirectoryItem? item) { if (item == null || InstallDirectories.Count <= 1) return; InstallDirectories.Remove(item); } [RelayCommand] private void GoBack() { _navigationService.GoBack(); } } public partial class InstallDirectoryItem : ObservableObject { [ObservableProperty] private string _path; public Guid Id { get; } = Guid.NewGuid(); public InstallDirectoryItem(string path) { _path = path; } } public class CultureItem { public string Code { get; } public string DisplayName { get; } public CultureItem(string code, string displayName) { Code = code; DisplayName = displayName; } public override string ToString() => DisplayName; }