using System.Text.Json; using View_by_Distance.Shared.Models; namespace View_by_Distance.Property.Models.Stateless; public class Container { private static (int f, List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)>) GetFileHolderGroupCollection(Configuration configuration, A_Property propertyLogic, string searchPattern, List topDirectories) { List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> results = new(); int? id; int parsedId; string idFile; string[] lines; const int zero = 0; List<(string File, int? Id)> files = new(); List<(int g, string sourceDirectory, string[] sourceDirectoryFiles)> collection; (int f, collection) = Shared.Models.Stateless.Methods.IFileHolder.GetGroupCollection(configuration.RootDirectory, configuration.MaxImagesInDirectoryForTopLevelFirstPass, propertyLogic.Reverse, searchPattern, topDirectories); foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles) in collection) { files.Clear(); foreach (string sourceDirectoryFile in sourceDirectoryFiles) { if (sourceDirectoryFile.EndsWith(".id")) continue; id = null; idFile = $"{sourceDirectoryFile}.id"; if (sourceDirectoryFiles.Contains(idFile)) { lines = File.ReadAllLines(idFile); File.Delete(idFile); if (lines.Any() && int.TryParse(lines[zero], out parsedId)) id = parsedId; }; files.Add(new(sourceDirectoryFile, id)); } results.Add(new(g, sourceDirectory, (from l in files select new FileHolder(l.File, l.Id)).ToArray())); } return new(f, results); } private static void ParallelFor(List<(string, string[])> jsonCollection, int i, int length, List<(string, List<(string, Shared.Models.Property?)>)> results) { string key; string json; Shared.Models.Property? property; (string sourceDirectory, string[] sourceDirectoryFiles) = jsonCollection[i]; List<(string, Shared.Models.Property?)> collection = new(); foreach (string sourceDirectoryFile in sourceDirectoryFiles) { json = File.ReadAllText(sourceDirectoryFile); key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length); property = JsonSerializer.Deserialize(json); collection.Add(new(sourceDirectoryFile, property)); } lock (results) results.Add(new(sourceDirectory, collection)); } private static List<(string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> GetCollection(string rootDirectory, List<(string sourceDirectory, string[] SourceDirectoryFiles)> jsonCollection) { List<(string, List<(string, Shared.Models.Property?)>)> results = new(); int length = rootDirectory.Length; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount }; _ = Parallel.For(0, jsonCollection.Count, parallelOptions, (i, state) => ParallelFor(jsonCollection, i, length, results)); return results; } private static Item GetNewItem(Configuration configuration, string relativePath, FileHolder sourceDirectoryFileHolder) { Item result; Shared.Models.Property? property = null; bool isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(sourceDirectoryFileHolder.ExtensionLowered); result = new(sourceDirectoryFileHolder, relativePath, sourceDirectoryFileHolder, isValidImageFormatExtension, property, null, null, null); return result; } private static (int, Shared.Models.Container[]) GetContainers(Configuration configuration, A_Property propertyLogic, string aPropertySingletonDirectory, List<(int, string, FileHolder[])> fileHolderGroupCollection, List<(string, List<(string, Shared.Models.Property?)>)> collectionFromJson) { int result = 0; Shared.Models.Container[] results; Item item; int length; int additional; string inferred; List items; const int last = 9; string keyWithJson; string relativePath; bool fileSizeChanged; FileHolder fileHolder; FileHolder keyFileHolder; bool lastWriteTimeChanged; bool isValidImageFormatExtension; List keySourceDirectories; Shared.Models.Container container; Dictionary keyValuePairs = new(); Dictionary fileHolderKeyValuePairs = new(); length = configuration.RootDirectory.Length; foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection) in fileHolderGroupCollection) { foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection) { relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length, forceExtensionToLower: true); if (fileHolderKeyValuePairs.ContainsKey(relativePath)) throw new NotSupportedException(); fileHolderKeyValuePairs.Add(relativePath, new(sourceDirectory, sourceDirectoryFileHolder)); } } length = aPropertySingletonDirectory.Length; foreach ((string _, List<(string, Shared.Models.Property?)> collection) in collectionFromJson) { if (!collection.Any()) continue; items = new(); keySourceDirectories = new(); foreach ((string sourceDirectoryFile, Shared.Models.Property? property) in collection) { fileHolder = new(sourceDirectoryFile); keyWithJson = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFile, length, forceExtensionToLower: false); relativePath = keyWithJson[..^5]; if (!fileHolderKeyValuePairs.ContainsKey(relativePath)) { inferred = string.Concat(configuration.RootDirectory, relativePath); keyFileHolder = new(inferred); if (keyFileHolder.ExtensionLowered is ".json") continue; keySourceDirectories.Add(string.Concat(keyFileHolder.DirectoryName)); isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered); item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, true, null, null); items.Add(item); } else { keyFileHolder = fileHolderKeyValuePairs[relativePath].FileHolder; keySourceDirectories.Add(fileHolderKeyValuePairs[relativePath].SourceDirectory); if (!fileHolderKeyValuePairs.Remove(relativePath)) throw new Exception(); if (keyFileHolder.ExtensionLowered is ".json") continue; isValidImageFormatExtension = configuration.ValidImageFormatExtensions.Contains(keyFileHolder.ExtensionLowered); if (property?.Id is null || property?.Width is null || property?.Height is null) item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, null, null); else { fileSizeChanged = property.FileSize != keyFileHolder.Length; lastWriteTimeChanged = configuration.PropertiesChangedForProperty || property.LastWriteTime != keyFileHolder.LastWriteTime; item = new(fileHolder, relativePath, keyFileHolder, isValidImageFormatExtension, property, false, fileSizeChanged, lastWriteTimeChanged); } items.Add(item); } } if (items.Any()) { result += items.Count; if (keySourceDirectories.Distinct().Count() != 1) continue; container = new(last, items, keySourceDirectories[0]); keyValuePairs.Add(keySourceDirectories[0], container); } } length = configuration.RootDirectory.Length; foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFileHolderCollection) in fileHolderGroupCollection) { items = new(); propertyLogic.SetAngleBracketCollection(sourceDirectory); foreach (FileHolder sourceDirectoryFileHolder in sourceDirectoryFileHolderCollection) { relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(sourceDirectoryFileHolder.FullName, length, forceExtensionToLower: true); if (!fileHolderKeyValuePairs.ContainsKey(relativePath)) continue; if (!fileHolderKeyValuePairs.Remove(relativePath)) throw new Exception(); if (sourceDirectoryFileHolder.ExtensionLowered is ".json") continue; item = GetNewItem(configuration, relativePath, sourceDirectoryFileHolder); items.Add(item); } if (sourceDirectory == configuration.RootDirectory || items.Any()) { if (!keyValuePairs.ContainsKey(sourceDirectory)) { result += items.Count; container = new(g, items, sourceDirectory); keyValuePairs.Add(sourceDirectory, container); } else { container = keyValuePairs[sourceDirectory]; (items, additional) = Shared.Models.Stateless.Methods.IItem.GetMerged(container.Items, items); result += additional; container = new(container.G, items, container.SourceDirectory); keyValuePairs[sourceDirectory] = container; } } } if (fileHolderKeyValuePairs.Any()) throw new NotSupportedException("Unmapped left!"); results = (from l in keyValuePairs orderby l.Value.G, l.Value.Items.Count select l.Value).ToArray(); return new(result, results); } private static void SetCollections(string aPropertySingletonDirectory, List otherCollection, List<(string, string[])> jsonCollection) { string searchPattern = "*"; (string, string[])[] collection = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(aPropertySingletonDirectory, searchPattern).ToArray(); foreach ((string sourceDirectory, string[] files) in collection) { otherCollection.AddRange(files.Where(l => !l.EndsWith(".json"))); jsonCollection.Add(new(sourceDirectory, files.Where(l => l.EndsWith(".json")).ToArray())); } } private static void DeleteAbandoned(Configuration configuration, string aPropertySingletonDirectory, List otherCollection, List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> fileHolderGroupCollection) { string relativePath; string checkFileName; string? checkDirectoryName; List checkCollection = new(); checkCollection.AddRange(otherCollection); int length = configuration.RootDirectory.Length; foreach ((int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles) in fileHolderGroupCollection) { foreach (FileHolder fileHolder in sourceDirectoryFiles) { relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(fileHolder.FullName, length); checkFileName = Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath)); checkDirectoryName = Path.GetDirectoryName(checkFileName); if (string.IsNullOrEmpty(checkDirectoryName) || !Directory.Exists(checkDirectoryName)) continue; if (!checkCollection.Remove(checkFileName)) File.WriteAllText(checkFileName, string.Empty); } } foreach (string file in checkCollection) File.Delete(file); } public static (int, int, int, Shared.Models.Container[]) GetContainers(Configuration configuration, A_Property propertyLogic) { Shared.Models.Container[] results; string searchPattern = "*"; List topDirectories = new(); List otherCollection = new(); List<(string, string[])> jsonCollection = new(); List<(int g, string sourceDirectory, FileHolder[] sourceDirectoryFiles)> fileHolderGroupCollection; string aPropertySingletonDirectory = IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}"); SetCollections(aPropertySingletonDirectory, otherCollection, jsonCollection); (int f, fileHolderGroupCollection) = GetFileHolderGroupCollection(configuration, propertyLogic, searchPattern, topDirectories); DeleteAbandoned(configuration, aPropertySingletonDirectory, otherCollection, fileHolderGroupCollection); List<(string sourceDirectory, List<(string sourceDirectoryFile, Shared.Models.Property? property)> collection)> collectionFromJson; collectionFromJson = GetCollection(aPropertySingletonDirectory, jsonCollection); (int t, results) = GetContainers(configuration, propertyLogic, aPropertySingletonDirectory, fileHolderGroupCollection, collectionFromJson); int j = jsonCollection.Select(l => l.Item2.Length).Sum(); return (j, f, t, results); } }