private void PopulateUI()
        {
            bool deleteConfirmationCallback(InstalledDLCMod mod)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_cannotDeleteModsWhileXIsRunning, Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }
                if (SelectedTarget.TextureModded)
                {
                    var res = M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_deletingXwhileAlotInstalledUnsupported, mod.ModName), M3L.GetString(M3L.string_deletingWillPutAlotInUnsupportedConfig), MessageBoxButton.YesNo, MessageBoxImage.Error);
                    return(res == MessageBoxResult.Yes);
                }
                return(M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_removeXFromTheGameInstallationQuestion, mod.ModName), M3L.GetString(M3L.string_confirmDeletion), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            void notifyDeleted()
            {
                PopulateUI();
            }

            SelectedTarget.PopulateDLCMods(true, deleteConfirmationCallback, notifyDeleted);

            bool restoreBasegamefileConfirmationCallback(string filepath)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_cannotRestoreFilesWhileXIsRunning, Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }
                if (SelectedTarget.TextureModded && filepath.RepresentsPackageFilePath())
                {
                    if (!Settings.DeveloperMode)
                    {
                        M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_restoringXWhileAlotInstalledIsNotAllowed, Path.GetFileName(filepath)), M3L.GetString(M3L.string_cannotRestorePackageFiles), MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                    else
                    {
                        var res = M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_restoringXwhileAlotInstalledLikelyBreaksThingsDevMode, Path.GetFileName(filepath)), M3L.GetString(M3L.string_invalidTexturePointersWarning), MessageBoxButton.YesNo, MessageBoxImage.Warning);
                        return(res == MessageBoxResult.Yes);
                    }
                }
                return(M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_restoreXquestion, Path.GetFileName(filepath)), M3L.GetString(M3L.string_confirmRestoration), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            bool restoreSfarConfirmationCallback(string sfarPath)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_cannotRestoreFilesWhileXIsRunning, Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }

                if (SelectedTarget.TextureModded)
                {
                    if (!Settings.DeveloperMode)
                    {
                        M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_restoringSfarsAlotBlocked), M3L.GetString(M3L.string_cannotRestoreSfarFiles), MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                    else
                    {
                        var res = M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_restoringSfarsAlotDevMode), M3L.GetString(M3L.string_invalidTexturePointersWarning), MessageBoxButton.YesNo, MessageBoxImage.Warning);
                        return(res == MessageBoxResult.Yes);
                    }
                }
                //Todo: warn of unpacked file deletion
                return(M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_interp_restoreXquestion, sfarPath), M3L.GetString(M3L.string_confirmRestoration), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            void notifyStartingSfarRestoreCallback()
            {
                SFARBeingRestored = true;
            }

            void notifyStartingBasegameFileRestoreCallback()
            {
                BasegameFilesBeingRestored = true;
            }

            void notifyRestoredCallback(object itemRestored)
            {
                if (itemRestored is GameTarget.ModifiedFileObject mf)
                {
                    Application.Current.Dispatcher.Invoke(delegate { SelectedTarget.ModifiedBasegameFiles.Remove(mf); });
                    bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                    if (!resetBasegameFilesBeingRestored)
                    {
                        resetBasegameFilesBeingRestored = !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                    }
                    if (resetBasegameFilesBeingRestored)
                    {
                        BasegameFilesBeingRestored = false;
                    }
                }
                else if (itemRestored is GameTarget.SFARObject ms)
                {
                    if (!ms.IsModified)
                    {
                        SelectedTarget.ModifiedSFARFiles.Remove(ms);
                    }
                    bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                    if (!resetSfarsBeingRestored)
                    {
                        resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                    }
                    if (resetSfarsBeingRestored)
                    {
                        SFARBeingRestored = false;
                    }
                }
                else if (itemRestored == null)
                {
                    //restore failed.
                    bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                    if (!resetSfarsBeingRestored)
                    {
                        resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                    }
                    if (resetSfarsBeingRestored)
                    {
                        SFARBeingRestored = false;
                    }
                    bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                    if (!resetBasegameFilesBeingRestored)
                    {
                        resetBasegameFilesBeingRestored = !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                    }
                    if (resetBasegameFilesBeingRestored)
                    {
                        BasegameFilesBeingRestored = false;
                    }
                }
            }

            SelectedTarget.PopulateModifiedBasegameFiles(restoreBasegamefileConfirmationCallback,
                                                         restoreSfarConfirmationCallback,
                                                         notifyStartingSfarRestoreCallback,
                                                         notifyStartingBasegameFileRestoreCallback,
                                                         notifyRestoredCallback);
            SFARBeingRestored = false;
        }
        /// <summary>
        /// This method is run on a background thread so all UI calls needs to be wrapped
        /// </summary>
        private void PopulateUI()
        {
            BackgroundWorker bw = new BackgroundWorker();

            bw.DoWork += (a, b) =>
            {
                bool deleteConfirmationCallback(InstalledDLCMod mod)
                {
                    if (Utilities.IsGameRunning(SelectedTarget.Game))
                    {
                        M3L.ShowDialog(Window.GetWindow(this),
                                       M3L.GetString(M3L.string_interp_cannotDeleteModsWhileXIsRunning,
                                                     Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning),
                                       MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }

                    if (SelectedTarget.TextureModded)
                    {
                        var res = M3L.ShowDialog(Window.GetWindow(this),
                                                 M3L.GetString(M3L.string_interp_deletingXwhileAlotInstalledUnsupported, mod.ModName),
                                                 M3L.GetString(M3L.string_deletingWillPutAlotInUnsupportedConfig), MessageBoxButton.YesNo,
                                                 MessageBoxImage.Error);
                        return(res == MessageBoxResult.Yes);
                    }

                    return(M3L.ShowDialog(Window.GetWindow(this),
                                          M3L.GetString(M3L.string_interp_removeXFromTheGameInstallationQuestion, mod.ModName),
                                          M3L.GetString(M3L.string_confirmDeletion), MessageBoxButton.YesNo,
                                          MessageBoxImage.Warning) == MessageBoxResult.Yes);
                }

                void notifyDeleted()
                {
                    PopulateUI();
                }

                SelectedTarget.PopulateDLCMods(true, deleteConfirmationCallback, notifyDeleted);
                SelectedTarget.PopulateExtras();
                SelectedTarget.PopulateTextureInstallHistory();
                bool restoreBasegamefileConfirmationCallback(string filepath)
                {
                    if (Utilities.IsGameRunning(SelectedTarget.Game))
                    {
                        M3L.ShowDialog(Window.GetWindow(this),
                                       M3L.GetString(M3L.string_interp_cannotRestoreFilesWhileXIsRunning,
                                                     Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning),
                                       MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }

                    if (SelectedTarget.TextureModded && filepath.RepresentsPackageFilePath())
                    {
                        if (!Settings.DeveloperMode)
                        {
                            M3L.ShowDialog(Window.GetWindow(this),
                                           M3L.GetString(M3L.string_interp_restoringXWhileAlotInstalledIsNotAllowed,
                                                         Path.GetFileName(filepath)), M3L.GetString(M3L.string_cannotRestorePackageFiles),
                                           MessageBoxButton.OK, MessageBoxImage.Error);
                            return(false);
                        }
                        else
                        {
                            var res = M3L.ShowDialog(Window.GetWindow(this),
                                                     M3L.GetString(M3L.string_interp_restoringXwhileAlotInstalledLikelyBreaksThingsDevMode,
                                                                   Path.GetFileName(filepath)),
                                                     M3L.GetString(M3L.string_invalidTexturePointersWarning), MessageBoxButton.YesNo,
                                                     MessageBoxImage.Warning);
                            return(res == MessageBoxResult.Yes);
                        }
                    }

                    bool?holdingShift = Keyboard.Modifiers == ModifierKeys.Shift;

                    if (!holdingShift.Value)
                    {
                        holdingShift = null;
                    }
                    return(holdingShift ?? M3L.ShowDialog(Window.GetWindow(this),
                                                          M3L.GetString(M3L.string_interp_restoreXquestion, Path.GetFileName(filepath)),
                                                          M3L.GetString(M3L.string_confirmRestoration), MessageBoxButton.YesNo,
                                                          MessageBoxImage.Warning) == MessageBoxResult.Yes);
                }

                bool restoreSfarConfirmationCallback(string sfarPath)
                {
                    if (Utilities.IsGameRunning(SelectedTarget.Game))
                    {
                        M3L.ShowDialog(Window.GetWindow(this),
                                       M3L.GetString(M3L.string_interp_cannotRestoreFilesWhileXIsRunning,
                                                     Utilities.GetGameName(SelectedTarget.Game)), M3L.GetString(M3L.string_gameRunning),
                                       MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }

                    if (SelectedTarget.TextureModded)
                    {
                        if (!Settings.DeveloperMode)
                        {
                            M3L.ShowDialog(Window.GetWindow(this), M3L.GetString(M3L.string_restoringSfarsAlotBlocked),
                                           M3L.GetString(M3L.string_cannotRestoreSfarFiles), MessageBoxButton.OK,
                                           MessageBoxImage.Error);
                            return(false);
                        }
                        else
                        {
                            var res = M3L.ShowDialog(Window.GetWindow(this),
                                                     M3L.GetString(M3L.string_restoringSfarsAlotDevMode),
                                                     M3L.GetString(M3L.string_invalidTexturePointersWarning), MessageBoxButton.YesNo,
                                                     MessageBoxImage.Warning);
                            return(res == MessageBoxResult.Yes);
                        }
                    }

                    //Todo: warn of unpacked file deletion
                    bool?holdingShift = Keyboard.Modifiers == ModifierKeys.Shift;

                    if (!holdingShift.Value)
                    {
                        holdingShift = null;
                    }
                    return(holdingShift ?? M3L.ShowDialog(Window.GetWindow(this),
                                                          M3L.GetString(M3L.string_interp_restoreXquestion, sfarPath),
                                                          M3L.GetString(M3L.string_confirmRestoration), MessageBoxButton.YesNo,
                                                          MessageBoxImage.Warning) == MessageBoxResult.Yes);
                }

                void notifyStartingSfarRestoreCallback()
                {
                    SFARBeingRestored = true;
                }

                void notifyStartingBasegameFileRestoreCallback()
                {
                    BasegameFilesBeingRestored = true;
                }

                void notifyRestoredCallback(object itemRestored)
                {
                    if (itemRestored is GameTarget.ModifiedFileObject mf)
                    {
                        Application.Current.Dispatcher.Invoke(delegate
                        {
                            SelectedTarget.ModifiedBasegameFiles.Remove(mf);
                        });
                        bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                        if (!resetBasegameFilesBeingRestored)
                        {
                            resetBasegameFilesBeingRestored =
                                !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                        }

                        if (resetBasegameFilesBeingRestored)
                        {
                            BasegameFilesBeingRestored = false;
                        }
                    }
                    else if (itemRestored is GameTarget.SFARObject ms)
                    {
                        if (!ms.IsModified)
                        {
                            SelectedTarget.ModifiedSFARFiles.Remove(ms);
                        }

                        bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                        if (!resetSfarsBeingRestored)
                        {
                            resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                        }

                        if (resetSfarsBeingRestored)
                        {
                            SFARBeingRestored = false;
                        }
                    }
                    else if (itemRestored == null)
                    {
                        //restore failed.
                        bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                        if (!resetSfarsBeingRestored)
                        {
                            resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                        }

                        if (resetSfarsBeingRestored)
                        {
                            SFARBeingRestored = false;
                        }

                        bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                        if (!resetBasegameFilesBeingRestored)
                        {
                            resetBasegameFilesBeingRestored =
                                !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                        }

                        if (resetBasegameFilesBeingRestored)
                        {
                            BasegameFilesBeingRestored = false;
                        }
                    }
                }

                SelectedTarget.PopulateModifiedBasegameFiles(restoreBasegamefileConfirmationCallback,
                                                             restoreSfarConfirmationCallback,
                                                             notifyStartingSfarRestoreCallback,
                                                             notifyStartingBasegameFileRestoreCallback,
                                                             notifyRestoredCallback);
                SFARBeingRestored = false;

                SelectedTarget.PopulateASIInfo();
                SelectedTarget.PopulateBinkInfo();

                if (SelectedTarget != null && !SelectedTarget.TextureModded)
                {
                    NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"BasegameSourceIdentifier");
                    nbw.DoWork += (a, b) =>
                    {
                        foreach (var v in SelectedTarget.ModifiedBasegameFiles.ToList())
                        {
                            v.DetermineSource();
                        }
                    };
                    nbw.RunWorkerAsync();
                }
            };
            bw.RunWorkerAsync();
        }
        private void PopulateUI()
        {
            bool deleteConfirmationCallback(InstalledDLCMod mod)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Cannot delete mods while {Utilities.GetGameName(SelectedTarget.Game)} is running.", $"Game is running", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }
                if (SelectedTarget.ALOTInstalled)
                {
                    var res = Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Deleting {mod.ModName} while ALOT is installed will not cause the game to become broken, however you will not be able to install updates to ALOT without a full reinstallation (unsupported configuration).\n\nAre you sure you want to delete the DLC mod?", $"Deleting will put ALOT in unsupported configuration", MessageBoxButton.YesNo, MessageBoxImage.Error);
                    return(res == MessageBoxResult.Yes);
                }
                return(Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Remove {mod.ModName} from the game installation?", $"Confirm deletion", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            void notifyDeleted()
            {
                PopulateUI();
            }

            SelectedTarget.PopulateDLCMods(deleteConfirmationCallback, notifyDeleted);

            bool restoreBasegamefileConfirmationCallback(string filepath)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Cannot restore files while {Utilities.GetGameName(SelectedTarget.Game)} is running.", $"Game is running", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }
                if (SelectedTarget.ALOTInstalled && filepath.RepresentsPackageFilePath())
                {
                    if (!Settings.DeveloperMode)
                    {
                        Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restoring {Path.GetFileName(filepath)} while ALOT is installed is not allowed, as it will introduce invalid texture pointers into the installation.", $"Cannot restore package files", MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                    else
                    {
                        var res = Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restoring {Path.GetFileName(filepath)} while ALOT is installed will very likely introduce invalid texture pointers into the installation, which may cause black textures or game crashes due to empty mips. Please ensure you know what you are doing before continuing.", $"Invalid texture pointers warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                        return(res == MessageBoxResult.Yes);
                    }
                }
                return(Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restore {Path.GetFileName(filepath)}?", $"Confirm restoration", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            bool restoreSfarConfirmationCallback(string sfarPath)
            {
                if (Utilities.IsGameRunning(SelectedTarget.Game))
                {
                    Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Cannot restore files while {Utilities.GetGameName(SelectedTarget.Game)} is running.", $"Game is running", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }

                if (SelectedTarget.ALOTInstalled)
                {
                    if (!Settings.DeveloperMode)
                    {
                        Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restoring SFAR files while ALOT is installed is not allowed, as it will introduce invalid texture pointers into the installation.", $"Cannot restore SFAR files", MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                    else
                    {
                        var res = Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restoring SFARs while ALOT is installed will introduce invalid texture pointers into the installation, which will cause black textures and possibly cause the game to crash. This operation will also delete all unpacked files from the directory. Please ensure you know what you are doing before continuing.", $"Invalid texture pointers warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                        return(res == MessageBoxResult.Yes);
                    }
                }
                //Todo: warn of unpacked file deletion
                return(Xceed.Wpf.Toolkit.MessageBox.Show(Window.GetWindow(this), $"Restore {sfarPath}?", $"Confirm restoration", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
            }

            void notifyStartingSfarRestoreCallback()
            {
                SFARBeingRestored = true;
            }

            void notifyStartingBasegameFileRestoreCallback()
            {
                BasegameFilesBeingRestored = true;
            }

            void notifyRestoredCallback(object itemRestored)
            {
                if (itemRestored is GameTarget.ModifiedFileObject mf)
                {
                    Application.Current.Dispatcher.Invoke(delegate { SelectedTarget.ModifiedBasegameFiles.Remove(mf); });
                    bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                    if (!resetBasegameFilesBeingRestored)
                    {
                        resetBasegameFilesBeingRestored = !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                    }
                    if (resetBasegameFilesBeingRestored)
                    {
                        BasegameFilesBeingRestored = false;
                    }
                }
                else if (itemRestored is GameTarget.SFARObject ms)
                {
                    if (!ms.IsModified)
                    {
                        SelectedTarget.ModifiedSFARFiles.Remove(ms);
                    }
                    bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                    if (!resetSfarsBeingRestored)
                    {
                        resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                    }
                    if (resetSfarsBeingRestored)
                    {
                        SFARBeingRestored = false;
                    }
                }
                else if (itemRestored == null)
                {
                    //restore failed.
                    bool resetSfarsBeingRestored = SelectedTarget.ModifiedSFARFiles.Count == 0;
                    if (!resetSfarsBeingRestored)
                    {
                        resetSfarsBeingRestored = !SelectedTarget.ModifiedSFARFiles.Any(x => x.Restoring);
                    }
                    if (resetSfarsBeingRestored)
                    {
                        SFARBeingRestored = false;
                    }
                    bool resetBasegameFilesBeingRestored = SelectedTarget.ModifiedBasegameFiles.Count == 0;
                    if (!resetBasegameFilesBeingRestored)
                    {
                        resetBasegameFilesBeingRestored = !SelectedTarget.ModifiedBasegameFiles.Any(x => x.Restoring);
                    }
                    if (resetBasegameFilesBeingRestored)
                    {
                        BasegameFilesBeingRestored = false;
                    }
                }
            }

            SelectedTarget.PopulateModifiedBasegameFiles(restoreBasegamefileConfirmationCallback,
                                                         restoreSfarConfirmationCallback,
                                                         notifyStartingSfarRestoreCallback,
                                                         notifyStartingBasegameFileRestoreCallback,
                                                         notifyRestoredCallback);
            SFARBeingRestored = false;
        }