using System.Diagnostics; using System.Text.Json; using View_by_Distance.Metadata.Models.Stateless; using View_by_Distance.Property.Models; using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Stateless; namespace View_by_Distance.Metadata.Models; /// // Dictionary>> /// public class B_Metadata { private readonly Serilog.ILogger? _Log; private readonly bool _PropertiesChangedForMetadata; private readonly IPropertyConfiguration _PropertyConfiguration; private readonly bool _ForceMetadataLastWriteTimeToCreationTime; private readonly IReadOnlyDictionary _FileGroups; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; public B_Metadata(IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, string bResultsFullGroupDirectory) { _Log = Serilog.Log.ForContext(); _PropertyConfiguration = propertyConfiguration; _PropertiesChangedForMetadata = propertiesChangedForMetadata; _ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, bResultsFullGroupDirectory, new string[] { propertyConfiguration.ResultSingleton }); } public override string ToString() { string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); return result; } private Dictionary>> GetMetadataCollection(string subFile) { Dictionary>> results = new(); if (_Log is null) throw new NullReferenceException(nameof(_Log)); try { object? @object; string? tagDescription; List tagNames = new(); int type = (int)IExif.Tags.Orientation; string key = nameof(IExif.Tags.Orientation); IReadOnlyList directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(subFile); foreach (MetadataExtractor.Directory directory in directories) { if (!results.ContainsKey(directory.Name)) results.Add(directory.Name, new()); foreach (MetadataExtractor.Tag tag in directory.Tags) { tagNames.Add(tag.Name); if (string.IsNullOrEmpty(tag.Description)) continue; results[directory.Name].Add(new KeyValuePair(string.Concat(tag.Type, '\t', tag.Name), tag.Description)); } if (tagNames.Contains(key) && !results.ContainsKey(key)) { @object = directory.GetObject(type); if (@object is null) continue; tagDescription = @object.ToString(); if (string.IsNullOrEmpty(tagDescription)) continue; results.Add(key, new() { new(string.Concat(type, '\t', key), tagDescription) }); } } } catch (Exception) { _Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", subFile, ">")); } return results; } public (int, List>) GetMetadataCollection(List> subFileTuples, List parseExceptions, Shared.Models.MappingFromItem mappingFromItem) { List> results = new(); string json = string.Empty; string[] changesFrom = new string[] { nameof(A_Property) }; Dictionary>>? dictionary; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name); FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json")); if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); fileInfo.Refresh(); } if (_ForceMetadataLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime) { File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); fileInfo.Refresh(); } if (_PropertiesChangedForMetadata) dictionary = new(); else if (!fileInfo.Exists) dictionary = new(); else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old")) throw new ArgumentException("must be a *.json file"); else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) dictionary = new(); else { json = File.ReadAllText(fileInfo.FullName); try { dictionary = JsonSerializer.Deserialize>>>(json); if (dictionary is null) throw new Exception(); subFileTuples.Add(new Tuple(nameof(B_Metadata), fileInfo.LastWriteTime)); } catch (Exception) { dictionary = new(); parseExceptions.Add(nameof(B_Metadata)); } } if (dictionary is null || !dictionary.Any()) { dictionary = GetMetadataCollection(mappingFromItem.ImageFileHolder.FullName); json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions); bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) { if (!_ForceMetadataLastWriteTimeToCreationTime) subFileTuples.Add(new Tuple(nameof(B_Metadata), DateTime.Now)); else { File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); fileInfo.Refresh(); subFileTuples.Add(new Tuple(nameof(B_Metadata), fileInfo.CreationTime)); } } } foreach (KeyValuePair>> keyValuePair in dictionary) { foreach (KeyValuePair keyValue in keyValuePair.Value) results.Add(new(string.Concat(keyValuePair.Key, '\t', keyValue.Key), keyValue.Value)); } return new(dictionary.Count, results); } }