using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; using MPF.Core.Data; using MPF.UI.Core.ComboBoxItems; using MPF.UI.Core.Windows; using SabreTools.RedumpLib.Web; using WPFCustomMessageBox; namespace MPF.UI.Core.ViewModels { public class OptionsViewModel { #region Fields /// /// Parent OptionsWindow object /// public OptionsWindow Parent { get; } /// /// Current set of options /// public Options Options { get; } /// /// Flag for if settings were saved or not /// public bool SavedSettings { get; private set; } #endregion #region Lists /// /// List of available internal programs /// public List> InternalPrograms => PopulateInternalPrograms(); /// /// Current list of supported system profiles /// public List Systems => RedumpSystemComboBoxItem.GenerateElements().ToList(); #endregion /// /// Constructor /// public OptionsViewModel(OptionsWindow parent, Options baseOptions) { Parent = parent; Options = new Options(baseOptions); // Add handlers Parent.AaruPathButton.Click += BrowseForPathClick; Parent.DiscImageCreatorPathButton.Click += BrowseForPathClick; Parent.DefaultOutputPathButton.Click += BrowseForPathClick; Parent.AcceptButton.Click += OnAcceptClick; Parent.CancelButton.Click += OnCancelClick; Parent.RedumpLoginTestButton.Click += OnRedumpTestClick; // Update UI with new values Load(); } #region Load and Save /// /// Load any options-related elements /// private void Load() { Parent.InternalProgramComboBox.SelectedIndex = InternalPrograms.FindIndex(r => r == Options.InternalProgram); Parent.DefaultSystemComboBox.SelectedIndex = Systems.FindIndex(r => r == Options.DefaultSystem); Parent.RedumpPasswordBox.Password = Options.RedumpPassword; } /// /// Save any options-related elements /// private void Save() { var selectedInternalProgram = Parent.InternalProgramComboBox.SelectedItem as Element; Options.InternalProgram = selectedInternalProgram?.Value ?? InternalProgram.DiscImageCreator; var selectedDefaultSystem = Parent.DefaultSystemComboBox.SelectedItem as RedumpSystemComboBoxItem; Options.DefaultSystem = selectedDefaultSystem?.Value ?? null; Options.RedumpPassword = Parent.RedumpPasswordBox.Password; SavedSettings = true; } #endregion #region Population /// /// Get a complete list of supported internal programs /// private static List> PopulateInternalPrograms() { var internalPrograms = new List { InternalProgram.DiscImageCreator, InternalProgram.Aaru, InternalProgram.Redumper }; return internalPrograms.Select(ip => new Element(ip)).ToList(); } #endregion #region UI Commands /// /// Browse and set a path based on the invoking button /// private void BrowseForPath(System.Windows.Controls.Button button) { // If the button is null, we can't do anything if (button == null) return; // Strips button prefix to obtain the setting name string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button")); // TODO: hack for now, then we'll see bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath"; string currentPath = TextBoxForPathSetting(pathSettingName)?.Text; string initialDirectory = AppDomain.CurrentDomain.BaseDirectory; if (!shouldBrowseForPath && !string.IsNullOrEmpty(currentPath)) initialDirectory = Path.GetDirectoryName(Path.GetFullPath(currentPath)); CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog(initialDirectory); using (dialog) { DialogResult result = dialog.ShowDialog(); if (result == DialogResult.OK) { string path = string.Empty; bool exists = false; if (shouldBrowseForPath && dialog is FolderBrowserDialog folderBrowserDialog) { path = folderBrowserDialog.SelectedPath; exists = Directory.Exists(path); } else if (dialog is OpenFileDialog openFileDialog) { path = openFileDialog.FileName; exists = File.Exists(path); } if (exists) { Options[pathSettingName] = path; TextBoxForPathSetting(pathSettingName).Text = path; } else { CustomMessageBox.Show( "Specified path doesn't exist!", "Error", MessageBoxButton.OK, MessageBoxImage.Error ); } } } } /// /// Optionally save the current options and close the parent window /// private void OptionalSaveAndClose(bool save) { // Save if we're supposed to if (save) Save(); Parent.Close(); } /// /// Test Redump login credentials /// #if NET48 private bool? TestRedumpLogin() #else private async Task TestRedumpLogin() #endif { #if NET48 (bool? success, string message) = RedumpWebClient.ValidateCredentials(Parent.RedumpUsernameTextBox.Text, Parent.RedumpPasswordBox.Password); #else (bool? success, string message) = await RedumpHttpClient.ValidateCredentials(Parent.RedumpUsernameTextBox.Text, Parent.RedumpPasswordBox.Password); #endif if (success == true) CustomMessageBox.Show(Parent, message, "Success", MessageBoxButton.OK, MessageBoxImage.Information); else if (success == false) CustomMessageBox.Show(Parent, message, "Failure", MessageBoxButton.OK, MessageBoxImage.Error); else CustomMessageBox.Show(Parent, message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); return success; } #endregion #region UI Functionality /// /// Create an open folder dialog box /// private static FolderBrowserDialog CreateFolderBrowserDialog() => new FolderBrowserDialog(); /// /// Create an open file dialog box /// private static OpenFileDialog CreateOpenFileDialog(string initialDirectory) { return new OpenFileDialog() { InitialDirectory = initialDirectory, Filter = "Executables (*.exe)|*.exe", FilterIndex = 0, RestoreDirectory = true, }; } /// /// Find a TextBox by setting name /// /// Setting name to find /// TextBox for that setting private System.Windows.Controls.TextBox TextBoxForPathSetting(string name) => Parent.FindName(name + "TextBox") as System.Windows.Controls.TextBox; #endregion #region Event Handlers /// /// Handler for generic Click event /// private void BrowseForPathClick(object sender, EventArgs e) => BrowseForPath(sender as System.Windows.Controls.Button); /// /// Handler for AcceptButton Click event /// private void OnAcceptClick(object sender, EventArgs e) => OptionalSaveAndClose(true); /// /// Handler for CancelButtom Click event /// private void OnCancelClick(object sender, EventArgs e) => OptionalSaveAndClose(false); /// /// Test Redump credentials for validity /// #if NET48 private void OnRedumpTestClick(object sender, EventArgs e) => TestRedumpLogin(); #else private async void OnRedumpTestClick(object sender, EventArgs e) => _ = await TestRedumpLogin(); #endif #endregion } }