NHSE/NHSE.WinForms/Subforms/Program/ImageFetcher.cs
2020-12-24 23:53:40 -08:00

168 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using NHSE.Sprites;
namespace NHSE.WinForms
{
public sealed partial class ImageFetcher : Form
{
private const string Filename = "image.zip";
private static string ZipFilePath => Path.Combine(ItemSprite.PlatformAppDataPath, Filename);
private readonly IReadOnlyList<string> AllHosts;
public ImageFetcher()
{
InitializeComponent();
L_Status.Text = L_FileSize.Text = string.Empty;
var splitHosts = AllHosts = LoadHosts();
CB_HostSelect.Items.Clear();
foreach (var host in splitHosts)
CB_HostSelect.Items.Add(CleanUrl(host));
CB_HostSelect.SelectedIndex = 0; // set outside of initialise to update filesize via HEAD response
CheckFileStatusLabel();
}
private static string[] LoadHosts()
{
var hosts = Properties.Resources.hosts_images;
var splitHosts = hosts.Split(new[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
return splitHosts;
}
private void B_Download_Click(object sender, EventArgs e)
{
var path = ItemSprite.PlatformAppDataPath;
var hostSelected = AllHosts[CB_HostSelect.SelectedIndex];
SetUIDownloadState(false);
L_Status.Text = "Downloading...";
try
{
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
using var webClient = new WebClient();
webClient.DownloadFileCompleted += Completed;
webClient.DownloadProgressChanged += ProgressChanged;
webClient.DownloadFileAsync(new Uri(hostSelected), ZipFilePath);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message);
SetUIDownloadState(true);
}
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) => PBar_MultiUse.Value = e.ProgressPercentage;
private void Completed(object? sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
WinFormsUtil.Error(e.Error.Message, e.Error.InnerException == null ? string.Empty : e.Error.InnerException.Message);
SetUIDownloadState(true);
return;
}
PBar_MultiUse.Value = 100;
L_Status.Text = "Unzipping...";
UnzipFile();
}
private async void UnzipFile()
{
try
{
var outputFolderPath = ItemSprite.PlatformAppDataImagePath;
if (Directory.Exists(outputFolderPath)) // overwrite existing
Directory.Delete(outputFolderPath, true);
Directory.CreateDirectory(outputFolderPath);
await Task.Run(() => ZipFile.ExtractToDirectory(ZipFilePath, outputFolderPath)).ConfigureAwait(false);
SetUIDownloadState(true, true);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message);
SetUIDownloadState(true);
}
}
private void SetUIDownloadState(bool val, bool success = false)
{
ControlBox = val;
B_Download.Enabled = val;
PBar_MultiUse.Value = 0;
L_Status.Text = success ? "Images installed successfully." : string.Empty;
CheckFileStatusLabel();
if (success)
ItemSprite.Initialize(Core.GameInfo.GetStrings("en").itemlist);
if (File.Exists(ZipFilePath))
File.Delete(ZipFilePath);
}
private void CB_HostSelect_SelectedIndexChanged(object sender, EventArgs e)
{
CheckNetworkFileSizeAsync();
}
private async void CheckNetworkFileSizeAsync()
{
L_FileSize.Text = string.Empty;
try
{
using var webClient = new WebClient();
await webClient.OpenReadTaskAsync(new Uri(AllHosts[CB_HostSelect.SelectedIndex], UriKind.Absolute)).ConfigureAwait(false);
var hdr = webClient.ResponseHeaders?["Content-Length"];
if (hdr == null)
{
L_FileSize.Text = "Failed.";
return;
}
var totalSizeBytes = Convert.ToInt64(hdr);
var totalSizeMb = totalSizeBytes / 1e+6;
L_FileSize.Text = $"{totalSizeMb:0.##}MB";
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
L_FileSize.Text = ex.Message;
}
}
private static string CleanUrl(string url)
{
var uri = new Uri(url);
return uri.Segments.Length < 2 ? url : $"{uri.Host}/{uri.Segments[1]}";
}
private bool CheckFileStatusLabel() => L_ImgStatus.Visible = ItemSprite.SingleSpriteExists;
}
}