using System.Diagnostics; using System.Text.Json; using View_by_Distance.Metadata.Models.Stateless; using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Shared.Models.Stateless; namespace View_by_Distance.Metadata.Models; /// // Dictionary>> /// public class B_Metadata { public List AngleBracketCollection { get; } private readonly Serilog.ILogger? _Log; private readonly bool _PropertiesChangedForMetadata; private readonly bool _ForceMetadataLastWriteTimeToCreationTime; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; public static string DateTimeFormat() => "ddd MMM dd HH:mm:ss yyyy"; public B_Metadata(bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata) { AngleBracketCollection = new List(); _Log = Serilog.Log.ForContext(); _PropertiesChangedForMetadata = propertiesChangedForMetadata; _ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; } public override string ToString() { string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); return result; } public void SetAngleBracketCollection(Property.Models.Configuration configuration, string bResultsFullGroupDirectory, string sourceDirectory) { AngleBracketCollection.Clear(); AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(configuration, sourceDirectory, bResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "Metadata as key value pairs", collectionDescription: string.Empty, converted: true)); } 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(Property.Models.Configuration configuration, string bResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.MappingFromItem mappingFromItem) { List> results = new(); string json = string.Empty; string[] changesFrom = Array.Empty(); Dictionary>>? dictionary; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string bMetadataSingletonFile = Path.Combine(bResultsFullGroupDirectory, "{}", configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); FileInfo fileInfo = new(bMetadataSingletonFile); if (!fileInfo.FullName.Contains(configuration.ResultAllInOne) && !fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) throw new Exception(); string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); if (File.Exists(parentCheck)) { File.Move(parentCheck, fileInfo.FullName); fileInfo.Refresh(); } } 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 && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) 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); } }