using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Phares.Shared; using ShellProgressBar; using System.Collections.ObjectModel; using View_by_Distance.Copy.Distinct.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Copy.Distinct; public class CopyDistinct { private readonly AppSettings _AppSettings; private readonly string _WorkingDirectory; private readonly Configuration _Configuration; private readonly IsEnvironment _IsEnvironment; private readonly IConfigurationRoot _ConfigurationRoot; private readonly Property.Models.Configuration _PropertyConfiguration; private readonly ReadOnlyDictionary> _FileGroups; public CopyDistinct(List args, ILogger logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { if (isSilent) { } if (console is null) { } _AppSettings = appSettings; _IsEnvironment = isEnvironment; _WorkingDirectory = workingDirectory; _ConfigurationRoot = configurationRoot; Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _PropertyConfiguration = propertyConfiguration; _Configuration = configuration; logger?.LogInformation(propertyConfiguration.RootDirectory); (bool move, ReadOnlyCollection filesCollection, bool anyLenFiles, bool moveBack) = Verify(); ReadOnlyDictionary>> keyValuePairs = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, [appSettings.ResultDirectoryKey]); _FileGroups = keyValuePairs[appSettings.ResultDirectoryKey]; List lines = CopyDistinctFilesInDirectories(logger, move, filesCollection, anyLenFiles, moveBack); if (lines.Count != 0) File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); } private (bool, ReadOnlyCollection, bool, bool) Verify() { if (_AppSettings is null) throw new NullReferenceException(nameof(_AppSettings)); if (_IsEnvironment is null) throw new NullReferenceException(nameof(_IsEnvironment)); if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); if (_ConfigurationRoot is null) throw new NullReferenceException(nameof(_ConfigurationRoot)); if (_WorkingDirectory is null) throw new NullReferenceException(nameof(_WorkingDirectory)); if (_PropertyConfiguration is null) throw new NullReferenceException(nameof(_PropertyConfiguration)); bool moveBack; const bool useCeilingAverage = true; const string fileSearchFilter = "*"; const string directorySearchFilter = "*"; string copyTo = Path.GetFullPath(_AppSettings.CopyTo); bool move = copyTo == _PropertyConfiguration.RootDirectory; ReadOnlyCollection filesCollection = IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage); bool anyLenFiles = filesCollection.Any(l => l.Any(m => m.EndsWith("len"))); if (!move) moveBack = false; else { string directory = Path.Combine(_PropertyConfiguration.RootDirectory, _AppSettings.ResultDirectoryKey); if (!anyLenFiles) throw new NotSupportedException("Use Mirror-Length app first!"); if (string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey)) throw new NotSupportedException("Change appsettings!"); if (!Directory.Exists(directory)) moveBack = false; else { if (Directory.GetFiles(directory, "*", SearchOption.AllDirectories).Length == 0) moveBack = false; else { move = false; moveBack = true; } } } if (move && _AppSettings.IfCanUseId) throw new NotSupportedException("Not allowed because it would irreversible!"); return (move, new(filesCollection), anyLenFiles, moveBack); } private List CopyDistinctFilesInDirectories(ILogger? logger, bool move, ReadOnlyCollection filesCollection, bool anyLenFiles, bool moveBack) { List results = []; ProgressBar progressBar; string[] distinctDirectories; ConsoleKey? consoleKey = null; string message = nameof(CopyDistinct); List<(FilePath, string)> toDoCollection; int count = filesCollection.Select(l => l.Length).Sum(); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; if (moveBack) { if (!anyLenFiles) throw new NotSupportedException(); (distinctDirectories, toDoCollection) = GetMoveBackToDoCollection(_PropertyConfiguration, filesCollection); } else { progressBar = new(count, message, options); string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey; if (key != _PropertyConfiguration.ResultContent) throw new NotImplementedException("Changed but didn't update!"); ReadOnlyCollection> filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, filesCollection); (distinctDirectories, toDoCollection) = IDirectory.GetToDoCollection(_PropertyConfiguration, _AppSettings.CopyDuplicates, _AppSettings.IfCanUseId, filePathsCollection, _FileGroups, () => progressBar.Tick()); progressBar.Dispose(); } foreach (string distinctDirectory in distinctDirectories) { if (!Directory.Exists(distinctDirectory)) _ = Directory.CreateDirectory(distinctDirectory); } if (move) logger?.LogInformation($"Ready to Move {toDoCollection.Count} file(s)?"); else if (!moveBack) logger?.LogInformation($"Ready to Copy {toDoCollection.Count} file(s)?"); else logger?.LogInformation($"Ready to Move back {toDoCollection.Count} file(s)?"); for (int y = 0; y < int.MaxValue; y++) { if (move) logger?.LogInformation("Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files"); else if (!moveBack) logger?.LogInformation("Press \"Y\" key to copy file(s), \"N\" key to log file(s) or close console to not copy files"); else logger?.LogInformation("Press \"Y\" key to move back file(s), \"N\" key to log file(s) or close console to not move back files"); consoleKey = System.Console.ReadKey().Key; if (consoleKey is ConsoleKey.Y or ConsoleKey.N) break; } logger?.LogInformation(". . ."); if (consoleKey is null || consoleKey.Value != ConsoleKey.Y) { if (move || moveBack) logger?.LogInformation("Nothing moved!"); else logger?.LogInformation("Nothing copied!"); } else { progressBar = new(count, message, options); results.AddRange(IDirectory.CopyOrMove(toDoCollection, move, moveBack, () => progressBar.Tick())); progressBar.Dispose(); if (move || moveBack) logger?.LogInformation("Done moving"); else logger?.LogInformation("Done copying"); } return results; } private static (string[], List<(FilePath, string)>) GetMoveBackToDoCollection(Property.Models.Configuration propertyConfiguration, ReadOnlyCollection filesCollection) { List<(FilePath, string)> results = []; string key; string? value; string fileName; FilePath filePath; string? directory; FileHolder fileHolder; string destinationFile; List distinctFound = []; List distinctNeeded = []; List distinctDirectories = []; Dictionary nameToPath = []; for (int i = 1; i < 3; i++) { foreach (string[] files in filesCollection) { foreach (string file in files.Reverse()) { fileName = Path.GetFileName(file); if (fileName.EndsWith("len")) { key = fileName[..^3]; destinationFile = file[..^3]; if (nameToPath.ContainsKey(key)) continue; nameToPath.Add(key, destinationFile); } else { if (!distinctNeeded.Contains(file)) distinctNeeded.Add(file); if (!nameToPath.ContainsKey(fileName)) continue; if (distinctFound.Contains(file)) continue; distinctFound.Add(file); } } } } foreach (string[] files in filesCollection) { foreach (string file in files) { // if (distinctNeeded.Count != distinctFound.Count) // continue; fileName = Path.GetFileName(file); if (fileName.EndsWith("len")) continue; if (!nameToPath.TryGetValue(fileName, out value)) continue; directory = Path.GetDirectoryName(value); if (string.IsNullOrEmpty(directory)) continue; fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); filePath = FilePath.Get(propertyConfiguration, fileHolder, index: null); results.Add(new(filePath, value)); if (!distinctDirectories.Contains(directory)) distinctDirectories.Add(directory); } } return (distinctDirectories.ToArray(), results); } }