private async Task DownloadExcludedMod(ModExportTemplate modTemplate, DirectoryInfo fileLocation, ExtendedModInfo info, IProgress <double> progress, CancellationToken cancellationToken)
        {
            switch (modTemplate.MaskedExportMode)
            {
            case ExportMode.NewestVersion:
                var newestRelease = info.Releases.MaxBy(release => release.Version);
                if (newestRelease != null)
                {
                    await DownloadModRelease(modTemplate, newestRelease, fileLocation, progress, cancellationToken);
                }
                break;

            case ExportMode.SpecificVersion:
                var specificRelease = info.Releases.FirstOrDefault(release => release.Version == modTemplate.Version);
                if (specificRelease != null)
                {
                    await DownloadModRelease(modTemplate, specificRelease, fileLocation, progress, cancellationToken);
                }
                break;

            case ExportMode.FactorioVersion:
                var factorioRelease = info.Releases.Where(release => release.InfoFile.FactorioVersion == modTemplate.FactorioVersion).MaxBy(release => release.Version);
                if (factorioRelease != null)
                {
                    await DownloadModRelease(modTemplate, factorioRelease, fileLocation, progress, cancellationToken);
                }
                break;
            }
        }
        private async Task DownloadModRelease(ModExportTemplate modTemplate, ModRelease release, DirectoryInfo fileLocation, IProgress <double> progress, CancellationToken cancellationToken)
        {
            if (Mods.TryGetMod(modTemplate.Name, release.Version, out Mod installedMod))
            {
                modTemplate.Mod = installedMod;
                return;
            }

            string token;

            GlobalCredentials.Instance.LogIn(Window, out token);

            string fileName = Path.Combine(fileLocation.FullName, $"{modTemplate.Uid}+{release.FileName}");
            await ModWebsite.DownloadReleaseToFileAsync(release, GlobalCredentials.Instance.Username, token, fileName, progress, cancellationToken);
        }
        private async Task <ExtendedModInfo> GetModInfo(ModExportTemplate modTemplate)
        {
            ExtendedModInfo info = null;

            try
            {
                info = await ModWebsite.GetExtendedInfoAsync(modTemplate.Name);
            }
            catch (WebException ex)
            {
                if (ex.Status != WebExceptionStatus.ProtocolError)
                {
                    throw;
                }
            }

            return(info);
        }
        private async Task AddMod(ModExportTemplate modTemplate, DirectoryInfo fileLocation)
        {
            var fsInfo = GetIncludedFileOrDirectory(modTemplate, fileLocation);

            FileInfo file = fsInfo as FileInfo;

            if (file != null)
            {
                if (ModFile.TryLoadFromFile(file, out var modFile, true))
                {
                    Mod mod = await Mod.Add(modFile, Mods, Modpacks, false, true);

                    modTemplate.Mod = mod;
                    return;
                }
                else
                {
                    throw new InvalidOperationException("Invalid mod file.");
                }
            }
        private async Task DownloadIncludedMod(ModExportTemplate modTemplate, DirectoryInfo fileLocation, ExtendedModInfo info, IProgress <double> progress, CancellationToken cancellationToken)
        {
            var file = GetIncludedFileOrDirectory(modTemplate, fileLocation);

            if ((file == null) || !file.Exists) // File should exist, download if it doesn't
            {
                await DownloadExcludedMod(modTemplate, fileLocation, info, progress, cancellationToken);

                return;
            }

            ModRelease targetRelease = null;

            switch (modTemplate.MaskedExportMode)
            {
            case ExportMode.NewestVersion:
                targetRelease = info.Releases.MaxBy(release => release.Version);
                break;

            case ExportMode.SpecificVersion:
                targetRelease = info.Releases.FirstOrDefault(release => release.Version == modTemplate.Version);
                break;

            case ExportMode.FactorioVersion:
                targetRelease = info.Releases.Where(release => release.InfoFile.FactorioVersion == modTemplate.FactorioVersion).MaxBy(release => release.Version);
                break;
            }

            if (targetRelease != null)
            {
                var fileVersion = GetVersionFromFile(file);
                if (fileVersion != targetRelease.Version)
                {
                    file.Delete();
                    await DownloadModRelease(modTemplate, targetRelease, fileLocation, progress, cancellationToken);
                }
            }
        }
        private async Task DownloadIfMissing(ModExportTemplate modTemplate, DirectoryInfo fileLocation, IProgress <double> progress, CancellationToken cancellationToken)
        {
            progress.Report(0);

            var info = await GetModInfo(modTemplate);

            if (info != null)
            {
                if (modTemplate.Included)
                {
                    if (modTemplate.DownloadNewer)
                    {
                        await DownloadIncludedMod(modTemplate, fileLocation, info, progress, cancellationToken);
                    }
                    else
                    {
                        var file = GetIncludedFileOrDirectory(modTemplate, fileLocation);
                        if ((file == null) || !file.Exists)
                        {
                            await DownloadExcludedMod(modTemplate, fileLocation, info, progress, cancellationToken);                                 // File should exist, download if it doesn't
                        }
                    }
                }
                else
                {
                    var file = GetIncludedFileOrDirectory(modTemplate, fileLocation);
                    if ((file != null) && file.Exists)
                    {
                        file.DeleteRecursive();                                // File should not exist, delete if it does
                    }
                    await DownloadExcludedMod(modTemplate, fileLocation, info, progress, cancellationToken);
                }
            }

            progress.Report(1);
        }
 private FileSystemInfo GetIncludedFileOrDirectory(ModExportTemplate modTemplate, DirectoryInfo fileLocation)
 {
     return(fileLocation.EnumerateFileSystemInfos($"{modTemplate.Uid}+*").FirstOrDefault());
 }