public async void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            stopwatch.Stop();
            ThemeConfig theme = (ThemeConfig)e.UserState;

            if ((e.Error == null) && EnsureZipNotHtml())
            {
                cancelButton.Enabled = false;
                ThemeResult result = await Task.Run(
                    () => ThemeLoader.ExtractTheme(imagesZipDest, theme.themeId, theme));

                result.DoLeft(ThemeLoader.HandleError);
                this.Close();
            }
            else if (themeUriIndex >= themeUris.Count)
            {
                bool shouldRetry = ThemeLoader.PromptDialog(string.Format(_("Failed to " +
                                                                            "download images for the '{0}' theme. Do you want to try again?"),
                                                                          theme.themeId));

                if (shouldRetry)
                {
                    InitDownload(theme);
                }
                else
                {
                    ThemeLoader.HandleError(new FailedToDownloadImages(theme.themeId));
                }
            }
            else
            {
                themeUriIndex++;
                DownloadNext(theme);
            }
        }
        private void ImportNext()
        {
            if (ThemeManager.importPaths.Count > 0)
            {
                foreach (string themePath in ThemeManager.importPaths)
                {
                    importQueue.Enqueue(themePath);
                }

                numJobs += ThemeManager.importPaths.Count;
                ThemeManager.importPaths.Clear();
            }

            this.Invoke(new Action(() => UpdateTotalPercentage(0)));

            if (importQueue.Count > 0)
            {
                string themePath = importQueue.Peek();
                this.Invoke(new Action(() =>
                                       label1.Text = string.Format(_("Importing theme from {0}..."),
                                                                   Path.GetFileName(themePath))));

                ThemeResult result = ThemeManager.ImportTheme(themePath);
                result.Match(e => this.Invoke(new Action(() => ThemeLoader.HandleError(e))),
                             theme => ThemeManager.importedThemes.Add(theme));

                importQueue.Dequeue();
                ImportNext();
            }
            else
            {
                ThemeManager.importMode = false;
                this.Invoke(new Action(() => this.Close()));
            }
        }
        public static ThemeResult ExtractTheme(string zipPath, string themeId,
                                               ThemeConfig preloadedTheme = null)
        {
            if (!File.Exists(zipPath))
            {
                return(new ThemeResult(new FailedToFindLocation(themeId, zipPath)));
            }

            string      themePath = Path.Combine("themes", themeId);
            ThemeResult result;

            try
            {
                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
                {
                    if (preloadedTheme == null)
                    {
                        try
                        {
                            ZipArchiveEntry themeJson = archive.Entries.Single(
                                entry => Path.GetExtension(entry.Name) == ".json");
                            themeJson.ExtractToFile(Path.Combine(themePath, "theme.json"), true);
                        }
                        catch (InvalidOperationException)
                        {
                            return(new ThemeResult(new NoThemeJSONInZIP(themeId, zipPath)));
                        }

                        result = TryLoad(themeId);
                    }
                    else
                    {
                        Directory.CreateDirectory(themePath);
                        result = new ThemeResult(preloadedTheme);
                    }

                    ZipArchiveEntry[] imageEntries = archive.Entries.Where(
                        entry => Path.GetDirectoryName(entry.FullName) == "" &&
                        Path.GetExtension(entry.Name) != ".json").ToArray();

                    if (imageEntries.Length == 0)
                    {
                        return(new ThemeResult(new NoImagesInZIP(themeId, zipPath)));
                    }

                    foreach (ZipArchiveEntry imageEntry in imageEntries)
                    {
                        imageEntry.ExtractToFile(Path.Combine(themePath, imageEntry.Name), true);
                    }
                }
            }
            catch (InvalidDataException)
            {
                return(new ThemeResult(new InvalidZIP(themeId, zipPath)));
            }

            return(result);
        }