Files
Radioo_LincleLINK/LincleLINK/Logic/AddInstanceWindowLogic.cs
T

293 lines
9.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LincleLINK
{
public class AddInstanceWindowLogic : ViewModelBase
{
private string _instanceName;
public string InstanceName
{
get { return _instanceName; }
set
{
_instanceName = value;
OnPropertyChanged(nameof(InstanceName));
}
}
private string _dataPath;
public string DataPath
{
get { return _dataPath; }
set
{
_dataPath = value;
OnPropertyChanged(nameof(DataPath));
}
}
private bool _isCopyChecked;
public bool IsCopyChecked
{
get { return _isCopyChecked; }
set
{
_isCopyChecked = value;
OnPropertyChanged(nameof(IsCopyChecked));
}
}
private bool _isMoveChecked;
public bool IsMoveChecked
{
get { return _isMoveChecked; }
set
{
_isMoveChecked = value;
OnPropertyChanged(nameof(IsMoveChecked));
}
}
private ObservableCollection<string> _logList;
public ObservableCollection<string> LogList
{
get { return _logList; }
set
{
_logList = value;
}
}
private double ProgressStep;
private double _progress;
public double Progress
{
get { return _progress; }
set
{
_progress = value;
OnPropertyChanged(nameof(Progress));
}
}
private bool _uIEnabled;
public bool UIEnabled
{
get { return _uIEnabled; }
set
{
_uIEnabled = value;
OnPropertyChanged(nameof(UIEnabled));
}
}
public RelayCommand MakeInstanceCommand { get; set; }
public RelayCommand BrowseCommand { get; set; }
public AddInstanceWindowLogic()
{
MakeInstanceCommand = new RelayCommand(MakeInstance);
BrowseCommand = new RelayCommand(BrowseForFolder);
IsCopyChecked = true;
Progress = 0;
LogList = new();
UIEnabled = true;
}
public void BrowseForFolder(object o)
{
FolderBrowserDialog dialog = new();
dialog.ShowDialog();
DataPath = dialog.SelectedPath;
dialog.Dispose();
}
public async void MakeInstance(object o)
{
LogList.Add("Validating...");
UIEnabled = false;
bool validate_result = await Task.Run(() => ValidateInstance());
UIEnabled = true;
if (validate_result)
{
LogList.Add("Good to go!");
try
{
CreateInstance();
}
catch (Exception e)
{
LogList.Add(e.Message);
}
}
}
public bool ValidateInstance()
{
if (string.IsNullOrWhiteSpace(InstanceName))
{
System.Windows.Forms.MessageBox.Show("Instance name cannot be empty.",
"Empty instance name", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if (string.IsNullOrWhiteSpace(DataPath))
{
System.Windows.Forms.MessageBox.Show("Data path cannot be empty.",
"Empty data path", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
string[] existingInstances = Directory.GetFiles(MainWindowLogic.instanceDir, "*.json");
foreach (string instance in existingInstances)
{
if (InstanceName.ToLower() == Path.GetFileNameWithoutExtension(instance).ToLower())
{
System.Windows.Forms.MessageBox.Show("Instance with this name already exists.",
"Duplicate instance name", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
foreach (char c in InstanceName)
{
if (Path.GetInvalidFileNameChars().Contains(c))
{
System.Windows.Forms.MessageBox.Show("Instance name contains invalid characters.",
"Invalid characters", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
foreach (char c in DataPath)
{
if (Path.GetInvalidPathChars().Contains(c))
{
System.Windows.Forms.MessageBox.Show("Data path contains invalid characters",
"Invalid characters", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
// check if there is enough space for copying
if (IsCopyChecked)
{
DirectoryInfo files = new(DataPath);
long size_to_copy = 0;
foreach (var file in files.GetFiles("*", SearchOption.AllDirectories))
{
size_to_copy += file.Length;
}
var drives = DriveInfo.GetDrives();
long free_space = 0;
foreach (var drive in drives)
{
if (MainWindowLogic.currentDir.StartsWith(drive.Name))
{
free_space = drive.AvailableFreeSpace;
}
}
if (size_to_copy + 100000000 > free_space) // add a 100MB wiggle room
{
if (MessageBox.Show($"Current drive is low on disk space, do you want to continue? " +
$"Free space: {Instance.ReadableSize(free_space)}, Size of files about to copy: {Instance.ReadableSize(size_to_copy)}", "Low disk space!",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
return true;
}
else
{
return false;
}
}
}
return true;
}
public async void CreateInstance()
{
UIEnabled = false;
Progress = 0;
List<InstanceFile> iFiles = new();
List<string> directories = new();
long totalSize = 0;
int alreadyExists = 0;
long newsize = 0;
DirectoryInfo dInfo = new(DataPath);
var allFiles = dInfo.GetFiles("*", SearchOption.AllDirectories);
ProgressStep = 100D / (allFiles.Length + 2);
LogList.Add("Hashing...");
foreach (var file in allFiles)
{
string relativePath = Path.GetRelativePath(DataPath, Path.GetDirectoryName(file.FullName));
if (relativePath == ".")
{
relativePath = string.Empty;
}
string hash = await Task.Run(() => GetMD5Checksum(file.FullName));
string hashedFileName = hash + file.Extension;
//string hashedFileName = "test";
LogList.Add($"Hashing {file.FullName}");
if (IsCopyChecked == true && IsMoveChecked == false)
{
if (!File.Exists(Path.Combine(MainWindowLogic.dbDir, hashedFileName)))
{
await Task.Run(() => File.Copy(file.FullName, Path.Combine(MainWindowLogic.dbDir, hashedFileName)));
newsize += file.Length;
}
else alreadyExists++;
}
else if (IsCopyChecked == false && IsMoveChecked == true)
{
if (!File.Exists(Path.Combine(MainWindowLogic.dbDir, hashedFileName)))
{
await Task.Run(() => File.Move(file.FullName, Path.Combine(MainWindowLogic.dbDir, hashedFileName)));
newsize += file.Length;
}
else alreadyExists++;
}
InstanceFile iFile = new(file.Name, relativePath, file.Length, hashedFileName);
iFiles.Add(iFile);
totalSize += file.Length;
Progress += ProgressStep;
}
LogList.Add("Collecting directories...");
foreach (var dir in Directory.GetDirectories(DataPath, "*", SearchOption.AllDirectories))
{
directories.Add(Path.GetRelativePath(DataPath, dir));
}
Progress += ProgressStep;
Instance instance = new(iFiles, directories, totalSize, allFiles.Length, InstanceName);
var options = new JsonSerializerOptions { WriteIndented = true };
LogList.Add("Saving instance to file...");
instance.SaveToFile(options);
Progress += ProgressStep;
LogList.Add($"Instance added. {alreadyExists} files already exist. {Instance.ReadableSize(newsize)} added to the db.");
UIEnabled = true;
}
public static string GetMD5Checksum(string fileName)
{
using var md5 = MD5.Create();
using var stream = File.OpenRead(fileName);
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "");
}
}
}