using Microsoft.Extensions.Configuration; using Phares.Shared; using View_by_Distance.Not.Copy.Copy.Models; using View_by_Distance.Property.Models; using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Not.Copy.Copy; public class NotCopyCopy { private readonly Serilog.ILogger? _Log; private readonly AppSettings _AppSettings; private readonly List _Exceptions; private readonly IsEnvironment _IsEnvironment; private readonly Models.Configuration _Configuration; private readonly List> _FileKeyValuePairs; private readonly Dictionary>> _FilePropertiesKeyValuePairs; public NotCopyCopy(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { if (isSilent) { } if (args is null) { } if (console is null) { } _AppSettings = appSettings; if (appSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!"); _IsEnvironment = isEnvironment; _Exceptions = new List(); _Log = Serilog.Log.ForContext(); _FileKeyValuePairs = new List>(); _FilePropertiesKeyValuePairs = new Dictionary>>(); Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory); Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); _Configuration = configuration; if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null) throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!"); if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); if (!_IsEnvironment.Development) throw new Exception("This program only allows development environments!"); string searchPattern = "*"; long ticks = DateTime.Now.Ticks; List topDirectories = new(); List compareSourceGroupCollection; List selectedSourceGroupCollection; PropertyLogic propertyLogic = GetPropertyLogic(); List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection; groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(_Configuration.CompareSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); compareSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork)); topDirectories.Clear(); groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(configuration.SelectedSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection)); selectedSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true); if (appSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork)); string directoryName; List distinct = new(); List<(string Source, string[] Destination)> copyCollection = GetCopyCollection(compareSourceGroupCollection, selectedSourceGroupCollection); foreach ((string source, string[] destination) in copyCollection) { directoryName = Path.Combine(destination.Take(destination.Length - 1).ToArray()); if (distinct.Contains(directoryName)) continue; distinct.Add(directoryName); if (!Directory.Exists(directoryName)) _ = Directory.CreateDirectory(directoryName); } _Log.Information($"Ready to copy {copyCollection.Count} file(s)?"); for (int y = 0; y < int.MaxValue; y++) { _Log.Information("Press \"Y\" key to to copy file(s)"); if (Console.ReadKey().Key == ConsoleKey.Y) break; } _Log.Information(". . ."); int copied = 0; string fullFileName; foreach ((string source, string[] destination) in copyCollection) { if (copied % 500 == 0) _Log.Information($"{copied})"); fullFileName = Path.Combine(destination); if (File.Exists(fullFileName)) continue; File.Copy(source, fullFileName); copied += 1; } _Log.Information($"{copied} file(s) copied"); for (int y = 0; y < int.MaxValue; y++) { _Log.Information("Press \"Y\" key to continue or close console"); if (Console.ReadKey().Key == ConsoleKey.Y) break; } _Log.Information(". . ."); } private static void Verify(Models.Configuration configuration) { if (Path.GetPathRoot(configuration.SelectedSource) == configuration.SelectedSource) throw new Exception($"{nameof(configuration.SelectedSource)} should have at least one level!"); if (string.IsNullOrEmpty(configuration.CompareSource) || !Directory.Exists(configuration.CompareSource)) throw new Exception($"{nameof(configuration.CompareSource)} must have a value and exits!"); if (string.IsNullOrEmpty(configuration.EmptyDestination) || Directory.Exists(configuration.EmptyDestination)) throw new Exception($"{nameof(configuration.EmptyDestination)} can't exit!"); if (string.IsNullOrEmpty(configuration.SelectedSource) || !Directory.Exists(configuration.SelectedSource)) throw new Exception($"{nameof(configuration.SelectedSource)} must have a value and exits!"); if (configuration.SelectedSource.Length != configuration.CompareSource.Length) throw new Exception($"{nameof(configuration.SelectedSource)} and {nameof(configuration.CompareSource)} must be the same length!"); } private long LogDelta(long ticks, string methodName) { long result; if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds; _Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)"); result = DateTime.Now.Ticks; return result; } private PropertyLogic GetPropertyLogic() { PropertyLogic result; string[] verifyToSeason = Array.Empty(); if (_AppSettings.MaxDegreeOfParallelism is null) throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!"); if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason); return result; } private List<(string Source, string[] Destination)> GetCopyCollection(List compareSourceGroupCollection, List selectedSourceGroupCollection) { List<(string Source, string[] Destination)> results = new(); string key; string fileName; A_Property? property; string destinationDirectory; List directoryNames; List destinationCollection; string filteredSourceDirectoryFile; Dictionary keyValuePairs = new(); foreach (Group group in compareSourceGroupCollection) { for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) { property = group.PropertyCollection[i]; if (property is null) continue; key = string.Concat(group.SourceDirectory[_Configuration.CompareSource.Length..], Path.GetFileName(group.FilteredSourceDirectoryFiles[i])); keyValuePairs.Add(key, property); } } foreach (Group group in selectedSourceGroupCollection) { for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++) { destinationCollection = new(); property = group.PropertyCollection[i]; if (property is null) continue; filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i]; fileName = Path.GetFileName(filteredSourceDirectoryFile); key = string.Concat(group.SourceDirectory[_Configuration.SelectedSource.Length..], fileName); if (keyValuePairs.ContainsKey(key) && keyValuePairs[key].LastWriteTime == property.LastWriteTime) continue; destinationDirectory = string.Concat(_Configuration.EmptyDestination, group.SourceDirectory[_Configuration.SelectedSource.Length..]); directoryNames = Property.Models.Stateless.IPath.GetDirectoryNames(destinationDirectory); destinationCollection.AddRange(directoryNames); destinationCollection.Add(fileName); results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray())); } } return results; } }