/// <summary>
        /// Ensures that there are no installed mods in the launcher kit that use EXE custom installers.
        /// If there are, tells the user to either update them or uninstall them.
        /// This keeps repeating until there are no mods left, or the user presses cancel.
        /// Returns true when the program can continue;
        /// </summary>
        /// <param name="kitPath"></param>
        /// <param name="mods"></param>
        /// <returns></returns>
        static bool EnsureNoModsWithExeInstallers(string kitPath, KitInstalledMods mods)
        {
            // Search for EXE custom installers
            var modsWithExeInstallers = new List <KitMod>();

            foreach (var mod in mods.Mods)
            {
                if (mod.ConfiguratorPath != null && !mod.ConfiguratorPath.ToLowerInvariant().EndsWith(".xml"))
                {
                    modsWithExeInstallers.Add(mod);
                }
            }

            if (modsWithExeInstallers.Any())
            {
                string text = "The following mods have EXE custom installers (which are no longer supported, and have already been deprecated for years now):\n";
                foreach (var mod in modsWithExeInstallers)
                {
                    text += "  " + GetModName(mod) + "\n";
                }
                text += "\nPlease, update them or uninstall them. Clicking OK will open the Easy Uninstaller.";

                var result = MessageBox.Show(text, "Mods need to be updated/uninstalled", MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.Cancel)
                {
                    throw new OperationCanceledException();
                }

                var process = Process.Start(Path.Combine(kitPath, "Spore ModAPI Easy Uninstaller.exe"));
                process.WaitForExit();

                return(EnsureNoModsWithExeInstallers(kitPath, mods));
            }
            else
            {
                return(true);
            }
        }
        public static ImportResult Import(string kitPath)
        {
            Exception settingsReason = null;

            //ImportResult result = null;

            try
            {
                string configPath = Path.Combine(kitPath, "LauncherSettings.config");
                if (File.Exists(configPath))
                {
                    var kitSettings = new KitSettings();
                    kitSettings.Load(configPath);
                    ImportSettings(kitSettings);
                }
            }
            catch (Exception ex)
            {
                settingsReason = ex;
            }

            string modsPath = Path.Combine(kitPath, "InstalledMods.config");

            List <KitMod> skippedMods = new List <KitMod>();
            List <ImportFailureEventArgs> failedMods = new List <ImportFailureEventArgs>();
            bool hasRecord = File.Exists(modsPath);

            ModSkipped += (sneder, args) =>
            {
                if (sneder is KitMod skipped)
                {
                    skippedMods.Add(skipped);
                }
            };
            KitInstalledMods.ModImportFailed += (sneder, args) =>
            {
                if (sneder is ImportFailureEventArgs failure)
                {
                    failedMods.Add(failure);
                }
            };

            if (hasRecord)
            {
                var kitMods = new KitInstalledMods(modsPath);
                foreach (ImportFailureEventArgs fail in ImportMods(kitPath, kitMods))
                {
                    failedMods.Add(fail);
                }
            }

            //purge Launcher Kit shortcuts
            try
            {
                string[] desktopShortcutPaths = Directory.EnumerateFiles(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)).ToArray();
                foreach (string s in desktopShortcutPaths)
                {
                    YeetShortcutIfLauncherKit(s);
                }

                string   startMenuShortcutFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "Spore ModAPI Launcher Kit");
                string[] startMenuShortcutPaths  = Directory.EnumerateFiles(startMenuShortcutFolder).ToArray();
                foreach (string s in startMenuShortcutPaths)
                {
                    YeetShortcutIfLauncherKit(s);
                }
                if ((Directory.EnumerateFiles(startMenuShortcutFolder).Count() == 0) && (Directory.EnumerateDirectories(startMenuShortcutFolder).Count() == 0))
                {
                    Directory.Delete(startMenuShortcutFolder);
                }
            }
            catch { }

            //purge Launcher Kit locator path
            try
            {
                string locatorFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Spore ModAPI Launcher");
                if (Directory.Exists(locatorFolderPath))
                {
                    Directory.Move(locatorFolderPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ModAPILauncherSMMBKP"));
                }
            }
            catch { }

            return(new ImportResult(skippedMods, failedMods, hasRecord, settingsReason));
        }
        static IEnumerable <ImportFailureEventArgs> ImportMods(string kitPath, KitInstalledMods mods)
        {
            List <ImportFailureEventArgs> failures = new List <ImportFailureEventArgs>();


            EnsureNoModsWithExeInstallers(kitPath, mods);

            // Store the mods that didn't have a mod configs folder
            var modsWithNoConfig = new List <KitMod>();
            // Also keep track of which mods were already on the manager, so we can inform the user that we skipped them
            //var modsAlreadyInstalled = new List<KitMod>();

            string kitModConfigsPath = Path.Combine(kitPath, "ModConfigs");

            // Copy over the mod configs folders, creating XML identities for those mods that didn't have it
            foreach (var mod in mods.Mods)
            {
                try
                {
                    string managerModConfigPath = Path.Combine(Settings.ModConfigsPath, mod.Unique);

                    /*if (!Directory.Exists(managerModConfigPath))
                     *  managerModConfigPath = Path.Combine(Settings.ModConfigsPath, mod.Name);*/

                    if (Directory.Exists(managerModConfigPath))
                    {
                        //modsAlreadyInstalled.Add(mod);
                        ModSkipped?.Invoke(mod, null);
                        continue;
                    }


                    string modConfigPath = Path.Combine(kitModConfigsPath, mod.Unique);
                    if (!Directory.Exists(modConfigPath) && (!mod.Name.IsNullOrEmptyOrWhiteSpace()))
                    {
                        modConfigPath = Path.Combine(kitModConfigsPath, mod.Name);
                    }


                    if (!Directory.Exists(modConfigPath))
                    {
                        foreach (string dir in Directory.EnumerateDirectories(kitModConfigsPath))
                        {
                            string modInfoPath = Path.Combine(dir, "ModInfo.xml");
                            if (File.Exists(modInfoPath))
                            {
                                XDocument modInfo    = XDocument.Load(modInfoPath);
                                var       uniqueAttr = modInfo.Root.Attribute("unique");
                                if (uniqueAttr != null)
                                {
                                    if (uniqueAttr.Value == mod.Unique)
                                    {
                                        modConfigPath = dir;
                                        break;
                                    }
                                }
                            }
                        }
                    }


                    if (Directory.Exists(modConfigPath))
                    {
                        DirectoryCopy(modConfigPath, managerModConfigPath);

                        bool usesLegacyDlls = true;

                        if (!File.Exists(Path.Combine(managerModConfigPath, "ModInfo.xml")))
                        {
                            string displayName = mod.DisplayName;
                            if (displayName == null)
                            {
                                displayName = mod.Name;
                            }
                            if (displayName == null)
                            {
                                displayName = mod.Unique;
                            }
                            ModInstallation.CreateModInfoXml(mod.Unique, mod.Name, managerModConfigPath, out XDocument document);

                            foreach (ModFile file in mod.Files)
                            {
                                XElement fileEl  = new XElement("prerequisite", file.Name);
                                string   gameDir = file.GameDir.ToString();
                                if (!gameDir.IsNullOrEmptyOrWhiteSpace())
                                {
                                    fileEl.SetAttributeValue("game", gameDir);
                                }
                            }
                        }
                        else
                        {
                            var document = XDocument.Load(Path.Combine(managerModConfigPath, "ModInfo.xml"));

                            foreach (XElement element in document.Root.Elements() /*.Where(x => x.Name.LocalName.ToLowerInvariant() != "remove")*/)
                            {
                                foreach (ModFile file in GetModComponentFiles(element))
                                {
                                    mod.Files.Add(file);
                                }
                            }


                            var xmlVersionAttr = document.Root.Attribute("installerSystemVersion");
                            if (xmlVersionAttr != null && Version.TryParse(xmlVersionAttr.Value, out Version version) &&
                                version != ModIdentity.XmlModIdentityVersion1_0_0_0)
                            {
                                usesLegacyDlls = false;
                            }
                        }

                        if (usesLegacyDlls)
                        {
                            string legacyPath = Path.Combine(managerModConfigPath, "UseLegacyDLLs");
                            File.WriteAllText(legacyPath, string.Empty);
                            Permissions.GrantAccessFile(legacyPath);
                        }
                    }
                    else
                    {
                        modsWithNoConfig.Add(mod);
                    }


                    Dictionary <string, string> launcherKitToMgrDllPaths = new Dictionary <string, string>();

                    foreach (ModFile file in mod.Files)
                    {
                        if ((file.GameDir != ComponentGameDir.Spore) && (file.GameDir != ComponentGameDir.GalacticAdventures))
                        {
                            if (
                                file.Name.ToLowerInvariant().EndsWith("-disk.dll") ||
                                file.Name.ToLowerInvariant().EndsWith("-steam.dll") ||
                                file.Name.ToLowerInvariant().EndsWith("-steam_patched.dll")
                                )
                            {
                                string key = Path.Combine(kitPath, file.Name);
                                if (!launcherKitToMgrDllPaths.ContainsKey(key))
                                {
                                    launcherKitToMgrDllPaths.Add(key, Path.Combine(Settings.LegacyLibsPath, file.Name));
                                }
                            }
                            else
                            {
                                string key = Path.Combine(kitPath, "mLibs", file.Name);

                                if (!launcherKitToMgrDllPaths.ContainsKey(key))
                                {
                                    launcherKitToMgrDllPaths.Add(key, Path.Combine(Settings.ModLibsPath, file.Name));
                                }
                            }
                        }
                    }

                    /*if (mod.PurgeModInfo)
                     * {
                     *  string xmlPath = Path.Combine(managerModConfigPath, "ModInfo.xml");
                     *  if (File.Exists(xmlPath))
                     *  {
                     *      File.Delete(xmlPath);
                     *      ModInstallation.CreateModInfoXml(mod.Unique, mod.Name, managerModConfigPath, out XDocument document);
                     *  }
                     * }*/

                    foreach (string key in launcherKitToMgrDllPaths.Keys)
                    {
                        if (!File.Exists(launcherKitToMgrDllPaths[key]) && File.Exists(key))
                        {
                            File.Copy(key, launcherKitToMgrDllPaths[key]);
                            Permissions.GrantAccessFile(launcherKitToMgrDllPaths[key]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    failures.Add(new ImportFailureEventArgs(ex, mod));
                }
            }

            foreach (var mod in modsWithNoConfig)
            {
                try
                {
                    bool usesLegacyDlls = false;
                    Dictionary <string, string> launcherKitToMgrDllPaths = new Dictionary <string, string>();

                    // Try to gather the files if they still exist
                    var filesToCopy = new List <string>();
                    if (mod.ConfiguratorPath != null && File.Exists(mod.ConfiguratorPath))
                    {
                        filesToCopy.Add(mod.ConfiguratorPath);
                    }

                    foreach (var file in mod.Files)
                    {
                        string filePath = GetKitModFilePath(kitPath, file);
                        if (File.Exists(filePath))
                        {
                            filesToCopy.Add(filePath);
                        }
                        else
                        {
                            if (filePath.ToLowerInvariant().Contains(@"\mlibs\"))
                            {
                                filePath = Path.Combine(kitPath, file.Name);
                                if (File.Exists(filePath))
                                {
                                    filesToCopy.Add(filePath);
                                }
                            }
                        }

                        if (
                            filePath.ToLowerInvariant().EndsWith("-disk.dll") ||
                            filePath.ToLowerInvariant().EndsWith("-steam.dll") ||
                            filePath.ToLowerInvariant().EndsWith("-steam_patched.dll")
                            )
                        {
                            usesLegacyDlls = true;


                            string kitDllPath = Path.Combine(kitPath, Path.GetFileName(filePath));
                            string mgrDllPath = Path.Combine(Settings.LegacyLibsPath, Path.GetFileName(filePath));
                            //MessageBox.Show(kitDllPath + "\n\n\n" + mgrDllPath, "DLL PATHS");
                            if (!launcherKitToMgrDllPaths.ContainsKey(kitDllPath))
                            {
                                launcherKitToMgrDllPaths.Add(kitDllPath, mgrDllPath);
                            }
                        }
                        else if (filePath.ToLowerInvariant().Contains(@"\mlibs\"))
                        {
                            if (!launcherKitToMgrDllPaths.ContainsKey(filePath))
                            {
                                launcherKitToMgrDllPaths.Add(filePath, Path.Combine(Settings.ModLibsPath, Path.GetFileName(filePath)));
                            }
                        }
                    }


                    string managerModConfigPath = Path.Combine(Settings.ModConfigsPath, mod.Unique);
                    Directory.CreateDirectory(managerModConfigPath);
                    Permissions.GrantAccessDirectory(managerModConfigPath);

                    foreach (var file in filesToCopy)
                    {
                        string outPath = Path.Combine(managerModConfigPath, Path.GetFileName(file));
                        File.Copy(file, outPath);
                        Permissions.GrantAccessFile(outPath);
                    }


                    if (!File.Exists(Path.Combine(managerModConfigPath, "ModInfo.xml")))
                    {
                        string displayName = mod.DisplayName;
                        if (displayName == null)
                        {
                            displayName = mod.Name;
                        }
                        if (displayName == null)
                        {
                            displayName = mod.Unique;
                        }
                        ModInstallation.CreateModInfoXml(mod.Unique, mod.Name, managerModConfigPath, out XDocument document);
                    }
                    else
                    {
                        var document       = XDocument.Load(Path.Combine(managerModConfigPath, "ModInfo.xml"));
                        var xmlVersionAttr = document.Root.Attribute("installerSystemVersion");
                        if (xmlVersionAttr != null && Version.TryParse(xmlVersionAttr.Value, out Version version) &&
                            (version == ModIdentity.XmlModIdentityVersion1_0_0_0))
                        {
                            usesLegacyDlls = true;
                        }
                    }

                    if (usesLegacyDlls)
                    {
                        string legacyPath = Path.Combine(managerModConfigPath, "UseLegacyDLLs");
                        File.WriteAllText(legacyPath, string.Empty);
                        Permissions.GrantAccessFile(legacyPath);
                    }

                    foreach (string key in launcherKitToMgrDllPaths.Keys)
                    {
                        if (!File.Exists(launcherKitToMgrDllPaths[key]) && File.Exists(key))
                        {
                            File.Copy(key, launcherKitToMgrDllPaths[key]);
                            Permissions.GrantAccessFile(launcherKitToMgrDllPaths[key]);
                        }
                    }

                    /*if (mod.PurgeModInfo)
                     * {
                     *  string xmlPath = Path.Combine(managerModConfigPath, "ModInfo.xml");
                     *  if (File.Exists(xmlPath))
                     *  {
                     *      File.Delete(xmlPath);
                     *      ModInstallation.CreateModInfoXml(mod.Unique, mod.Name, managerModConfigPath, out XDocument document);
                     *  }
                     * }*/
                }
                catch (Exception ex)
                {
                    failures.Add(new ImportFailureEventArgs(ex, mod));
                }
            }

            foreach (KitMod mod in mods.Mods)
            {
                string managerModConfigPath = Path.Combine(Settings.ModConfigsPath, mod.Unique);

                string prepXmlPath = Path.Combine(managerModConfigPath, "ModInfo.xml");
                if (File.Exists(prepXmlPath))
                {
                    XDocument prepDoc        = XDocument.Load(prepXmlPath);
                    var       prepUniqueAttr = prepDoc.Root.Attribute("unique");
                    if (prepUniqueAttr != null)
                    {
                        if (prepUniqueAttr.Value != mod.Unique)
                        {
                            File.Delete(prepXmlPath);
                            ModInstallation.CreateModInfoXml(mod.Unique, mod.Name, managerModConfigPath, out XDocument document);
                        }
                    }
                }
            }

            /*if (modsAlreadyInstalled.Count > 0)
             * {
             *  string text = "The following mods were already installed on the Mod Manager, so they have been skipped:\n";
             *  foreach (var mod in modsAlreadyInstalled)
             *  {
             *      text += "  " + GetModName(mod) + "\n";
             *  }
             *  MessageBox.Show(text, "A few mods were skipped");
             * }*/
            return(failures);
        }