using System.Text.Json.Serialization; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Properties; namespace View_by_Distance.Property.Models; public class PropertyHolder { protected readonly bool? _Abandoned; protected readonly bool? _Changed; protected List _Faces; protected readonly FileInfo? _ImageFileInfo; protected readonly string _ImageFileNameWithoutExtension; protected readonly int _G; protected DateTime? _MinimumDateTime; protected bool? _Moved; protected List<(bool?, DateTime, PersonBirthday, double?)> _Named; protected readonly bool? _NoJson; protected A_Property? _Property; protected readonly int _R; protected readonly string _RelativePath; protected FileInfo? _ResizedFileInfo; protected readonly string _SourceDirectory; protected readonly string _SourceDirectoryFile; protected bool? _ValidImageFormatExtension; public bool? Abandoned => _Abandoned; public bool? Changed => _Changed; public List Faces => _Faces; public FileInfo? ImageFileInfo => _ImageFileInfo; public string ImageFileNameWithoutExtension => _ImageFileNameWithoutExtension; public int G => _G; public DateTime? MinimumDateTime => _MinimumDateTime; public bool? Moved => _Moved; public bool? NoJson => _NoJson; public List<(bool? isWrongYear, DateTime minimumDateTime, PersonBirthday personBirthday, double? pixelPercentage)> Named => _Named; public A_Property? Property => _Property; public int R => _R; public string RelativePath => _RelativePath; public FileInfo? ResizedFileInfo => _ResizedFileInfo; public string SourceDirectory => _SourceDirectory; public string SourceDirectoryFile => _SourceDirectoryFile; public bool? ValidImageFormatExtension => _ValidImageFormatExtension; public PropertyHolder() { _G = -1; _R = -1; _Faces = new(); _Named = new(); _RelativePath = string.Empty; _SourceDirectory = string.Empty; _SourceDirectoryFile = string.Empty; _ImageFileNameWithoutExtension = string.Empty; } [JsonConstructor] public PropertyHolder(int g, string sourceDirectory, string sourceDirectoryFile, string relativePath, int r, FileInfo? imageFileInfo, A_Property? property, bool? abandoned, bool? changed, bool? moved, bool? validImageFormatExtension) { _G = g; _R = r; _Faces = new(); _Moved = moved; _Named = new(); _Changed = changed; _Property = property; _Abandoned = abandoned; _NoJson = abandoned is null; _RelativePath = relativePath; _ImageFileInfo = imageFileInfo; _SourceDirectory = sourceDirectory; _SourceDirectoryFile = sourceDirectoryFile; _ValidImageFormatExtension = validImageFormatExtension; _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); if (imageFileInfo is null) _ImageFileNameWithoutExtension = string.Empty; else _ImageFileNameWithoutExtension = Path.GetFileNameWithoutExtension(imageFileInfo.FullName); if (imageFileInfo is not null && imageFileInfo.Extension is ".json") throw new ArgumentException("Can not be a *.json file!"); if (!sourceDirectoryFile.EndsWith(".json") && !sourceDirectoryFile.EndsWith(".old")) throw new ArgumentException("Must be a *.json or *.old file!"); } internal void SetValidImageFormatExtension(bool isValidImageFormatExtension) => _ValidImageFormatExtension = isValidImageFormatExtension; internal void SetMoved(bool moved) => _Moved = moved; public static string GetWrongYearFlag(bool? isWrongYear) => isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "="; public void SetResizedFileInfo(FileInfo fileInfo) => _ResizedFileInfo = fileInfo; public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value); public void Update(A_Property property) { _Property = property; _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); } public static void AddToNamed(PropertyLogic propertyLogic, PropertyHolder[] filteredPropertyHolderCollection) { bool? isWrongYear; string[] segments; string[] personKeys; double? pixelPercentage; DateTime minimumDateTime; PropertyHolder propertyHolder; PersonBirthday? personBirthday; for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { propertyHolder = filteredPropertyHolderCollection[i]; if (propertyHolder.ImageFileInfo is null) continue; if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileInfo is null) continue; if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(propertyHolder.Property.Id.Value)) continue; minimumDateTime = Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property); personKeys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value]; (isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileInfo.FullName, minimumDateTime); for (int j = 0; j < personKeys.Length; j++) { segments = Shared.Models.Stateless.Methods.IPersonBirthday.GetSegments(personKeys[j]); personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeys[j]); if (personBirthday is null) continue; if (segments.Length <= 1 || !double.TryParse(segments[1], out double value)) pixelPercentage = null; else pixelPercentage = value; propertyHolder.Named.Add(new(isWrongYear, minimumDateTime, personBirthday, pixelPercentage)); } } } public static List<(PropertyHolder, (string, IFace?, (string, string, string, string))[])> GetCollection(PropertyLogic propertyLogic, PropertyHolder[] filteredPropertyHolderCollection, string dFacesContentDirectory) { List<(PropertyHolder, (string, IFace?, (string, string, string, string))[])> results = new(); string[] keys; string directory; string personKey; bool? isWrongYear; string[] segments; const int zero = 0; TimeSpan? timeSpan; string copyFileName; string copyDirectory; string? relativePath; string isWrongYearFlag; string shortcutFileName; string subDirectoryName; List indices = new(); List faceCollection; PropertyHolder propertyHolder; PersonBirthday? personBirthday; List<(string, IFace?, (string, string, string, string))> collection; for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) { indices.Clear(); personKey = string.Empty; copyFileName = string.Empty; copyDirectory = string.Empty; propertyHolder = filteredPropertyHolderCollection[i]; if (propertyHolder.ImageFileInfo is null) continue; relativePath = Path.GetDirectoryName($"C:{propertyHolder.RelativePath}"); if (string.IsNullOrEmpty(relativePath) || relativePath.Length < 3) continue; if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileInfo is null) continue; collection = new(); if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(propertyHolder.Property.Id.Value)) { faceCollection = new(); directory = Path.Combine(dFacesContentDirectory, $"Unnamed{relativePath[2..]}"); } else { faceCollection = propertyHolder.Faces; keys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value]; (isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileInfo.FullName, propertyHolder.MinimumDateTime.Value); isWrongYearFlag = GetWrongYearFlag(isWrongYear); subDirectoryName = $"{isWrongYearFlag}{propertyHolder.MinimumDateTime.Value:yyyy}"; if (!faceCollection.Any()) directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}", subDirectoryName); else if (keys.Length != 1) directory = Path.Combine(dFacesContentDirectory, $"Not Supported{relativePath[2..]}", subDirectoryName); else if (faceCollection.Count != 1) directory = Path.Combine(dFacesContentDirectory, $"Many{relativePath[2..]}", subDirectoryName); else { indices.Add(zero); segments = Shared.Models.Stateless.Methods.IPersonBirthday.GetSegments(keys[zero]); personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(keys[zero]); if (personBirthday is null) continue; timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(propertyHolder.MinimumDateTime.Value, isWrongYear, personBirthday); if (timeSpan.HasValue) { if (timeSpan.Value.Ticks < 0) subDirectoryName = "!---"; else subDirectoryName = $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}"; } personKey = segments[zero]; directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName); if (faceCollection[zero].Populated) copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName); else copyDirectory = Path.Combine(dFacesContentDirectory, "ImagesBut", personKey, subDirectoryName); copyFileName = Path.Combine(copyDirectory, $"{propertyHolder.Property.Id.Value}{propertyHolder.ResizedFileInfo.Extension}"); } } shortcutFileName = Path.Combine(directory, $"{propertyHolder.Property.Id.Value}.lnk"); if (string.IsNullOrEmpty(personKey) || !indices.Any()) collection.Add(new(personKey, null, (directory, copyDirectory, copyFileName, shortcutFileName))); else { foreach (int index in indices) collection.Add(new(personKey, faceCollection[index], (directory, copyDirectory, copyFileName, shortcutFileName))); } results.Add(new(propertyHolder, collection.ToArray())); } return results; } private static Dictionary> GetKeyValuePairs(string argZero, List propertyHolderCollections, string eDistanceCollectionDirectory) { Dictionary> results = new(); string key; string personKey; TimeSpan? timeSpan; string[] directories; string isWrongYearFlag; string facePopulatedKey; foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) { if (!propertyHolderCollection.Any()) continue; if (!propertyHolderCollection[0].SourceDirectory.StartsWith(argZero)) continue; foreach (PropertyHolder propertyHolder in propertyHolderCollection) { if (propertyHolder.ImageFileInfo is null || propertyHolder.Property is null || !propertyHolder.Named.Any()) continue; foreach ((bool? isWrongYear, DateTime minimumDateTime, PersonBirthday personBirthday, double? pixelPercentage) in propertyHolder.Named) { if (propertyHolder.MinimumDateTime is null) continue; if (pixelPercentage is null && (propertyHolder.Named.Count != 1 || propertyHolder.Faces.Count != 1)) continue; foreach (IFace face in propertyHolder.Faces) { if (pixelPercentage.HasValue && pixelPercentage.Value != face.Location.PixelPercentage) continue; personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday); timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday); if (face.Populated) facePopulatedKey = "Images"; else facePopulatedKey = "ImagesBut"; if (timeSpan.HasValue && timeSpan.Value.Ticks < 0) directories = new string[] { string.Empty, facePopulatedKey, personKey, "!---" }; else if (timeSpan.HasValue) directories = new string[] { string.Empty, facePopulatedKey, personKey, $"^{Math.Floor(timeSpan.Value.TotalDays / 365):000}" }; else { isWrongYearFlag = GetWrongYearFlag(isWrongYear); directories = new string[] { string.Empty, facePopulatedKey, personKey, $"{isWrongYearFlag}{propertyHolder.MinimumDateTime.Value:yyyy}" }; } key = string.Join('\t', directories); if (!results.ContainsKey(key)) results.Add(key, new()); directories[0] = eDistanceCollectionDirectory; results[key].Add(new(directories, personBirthday, face)); if (pixelPercentage is null) break; } } } } return results; } public static List<(string, PersonBirthday, IFace)[]> GetCollection(string argZero, List propertyHolderCollections, string eDistanceCollectionDirectory) { List<(string, PersonBirthday, IFace)[]> results = new(); string directory; List<(string, PersonBirthday, IFace)> group; Dictionary> keyValuePairs = GetKeyValuePairs(argZero, propertyHolderCollections, eDistanceCollectionDirectory); foreach (KeyValuePair> keyValuePair in keyValuePairs) { group = new(); foreach ((string[] directories, PersonBirthday personBirthday, IFace face) in keyValuePair.Value) { directory = Path.Combine(directories); group.Add(new(directory, personBirthday, face)); } results.Add(group.ToArray()); } return results; } }