using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Phares.Shared; using ShellProgressBar; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.Reflection; using System.Text; using View_by_Distance.Offset.Date.Time.Original.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Offset.Date.Time.Original; public class OffsetDateTimeOriginal { private record Record(FileHolder FileHolder, bool IsIgnoreExtension, bool IsValidImageFormatExtension, int? Id, DateTime DateTime); private readonly AppSettings _AppSettings; private readonly string _WorkingDirectory; private readonly Configuration _Configuration; private readonly IsEnvironment _IsEnvironment; private readonly IConfigurationRoot _ConfigurationRoot; private readonly Property.Models.Configuration _PropertyConfiguration; public OffsetDateTimeOriginal(List args, ILogger logger, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { if (isSilent) { } if (console is null) { } _AppSettings = appSettings; _IsEnvironment = isEnvironment; _WorkingDirectory = workingDirectory; _ConfigurationRoot = configurationRoot; Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _PropertyConfiguration = propertyConfiguration; _Configuration = configuration; logger?.LogInformation(propertyConfiguration.RootDirectory); Verify(); List lines = OffsetDateTimeOriginalFilesInDirectories(logger); if (lines.Count != 0) File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); } private void Verify() { if (_AppSettings is null) throw new NullReferenceException(nameof(_AppSettings)); if (_IsEnvironment is null) throw new NullReferenceException(nameof(_IsEnvironment)); if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); if (_ConfigurationRoot is null) throw new NullReferenceException(nameof(_ConfigurationRoot)); if (_WorkingDirectory is null) throw new NullReferenceException(nameof(_WorkingDirectory)); if (_PropertyConfiguration is null) throw new NullReferenceException(nameof(_PropertyConfiguration)); if (!_PropertyConfiguration.PopulatePropertyId) throw new NotSupportedException("Must have!"); } private List GetRecords(ASCIIEncoding asciiEncoding, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks) { List results = []; DateTime dateTime; int? id; string? message; DateTime[] dateTimes; FileHolder fileHolder; bool isIgnoreExtension; DateTime? dateTimeOriginal; bool isValidImageFormatExtension; string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { fileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(file); isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); (dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration, _PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding); if (message is not null) throw new Exception(message); if (id is null || dateTimeOriginal is null) continue; dateTime = dateTimeOriginal.Value.AddTicks(ticks); if (dateTime < minimumDateTime) continue; if (dateTime > maximumDateTime) continue; results.Add(new(fileHolder, isIgnoreExtension, isValidImageFormatExtension, id, dateTimeOriginal.Value.AddTicks(ticks))); } if (files.Length != results.Count) throw new Exception(); return results; } #pragma warning disable CA1416 private void DateFix(string sourceDirectory, ASCIIEncoding asciiEncoding, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks) { int? id; Bitmap bitmap; short type = 2; string checkFile; PropertyItem? propertyItem; string? ticksDirectory = null; const int dateTimeOriginal = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal; // 36867 for (int i = 0; i < int.MaxValue; i++) { ticksDirectory = Path.Combine(sourceDirectory, ticks.ToString()); if (!Directory.Exists(ticksDirectory)) { _ = Directory.CreateDirectory(ticksDirectory); break; } ticks++; } List records = GetRecords(asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, ticks); ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception(); string? message = nameof(OffsetDateTimeOriginal); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBar progressBar = new(records.Count, message, options); foreach (Record record in records) { progressBar.Tick(); if (ticksDirectory is null) throw new Exception(); checkFile = Path.Combine(ticksDirectory, record.FileHolder.Name); if (File.Exists(checkFile)) continue; propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, dateTimeOriginal, type, record.DateTime.ToString("yyyy:MM:dd HH:mm:ss")); bitmap = new(record.FileHolder.FullName); bitmap.SetPropertyItem(propertyItem); bitmap.Save(checkFile); bitmap.Dispose(); (_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration, _PropertyConfiguration.PopulatePropertyId, record.FileHolder, record.IsIgnoreExtension, record.IsValidImageFormatExtension, asciiEncoding); if (message is not null) throw new Exception(message); if (id is null || id.Value != record.Id) throw new Exception(); } progressBar.Dispose(); } #pragma warning restore CA1416 private void DateFix(ILogger? logger, string sourceDirectory) { string checkDirectory; ASCIIEncoding asciiEncoding = new(); long oneYearTicks = DateTime.MinValue.AddYears(1).Ticks; checkDirectory = Path.Combine(sourceDirectory, oneYearTicks.ToString()); if (Directory.Exists(checkDirectory)) DateFix(sourceDirectory, asciiEncoding, checkDirectory, DateTime.MinValue, DateTime.MaxValue, new TimeSpan(oneYearTicks - DateTime.MinValue.Ticks).Ticks); else { checkDirectory = Path.Combine(sourceDirectory, "1"); if (!Directory.Exists(checkDirectory)) logger?.LogError($"<{checkDirectory}> doesn't exist!"); else { string badDirectory = Path.Combine(sourceDirectory, "Bad"); string targetDirectory = Path.Combine(sourceDirectory, "Target"); string[] minimumDirectory = Directory.GetDirectories(targetDirectory, "*", SearchOption.TopDirectoryOnly); if (minimumDirectory.Length != 1) logger?.LogError($"<{checkDirectory}> doesn't exist!"); else { string format = "yyyy-MM-dd"; string[] maximumDirectory = Directory.GetDirectories(minimumDirectory.First(), "*", SearchOption.TopDirectoryOnly); string[] badFiles = !Directory.Exists(badDirectory) ? [] : Directory.GetFiles(badDirectory, "*", SearchOption.TopDirectoryOnly); string[] targetFiles = !Directory.Exists(targetDirectory) ? [] : Directory.GetFiles(targetDirectory, "*", SearchOption.TopDirectoryOnly); if (badFiles.Length != 1 || targetFiles.Length != 1 || maximumDirectory.Length != 1) logger?.LogError("bad file(s) or target file(s) or maximum directory doesn't equal 1!"); else { int? badId; int? targetId; string? badMessage; string? targetMessage; DateTime[] badDateTimes; bool badIsIgnoreExtension; DateTime[] targetDateTimes; bool targetIsIgnoreExtension; DateTime? badDateTimeOriginal; DateTime? targetDateTimeOriginal; FileHolder badFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(badFiles.First()); FileHolder targetFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(targetFiles.First()); bool badIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(badFileHolder.ExtensionLowered); bool targetIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(targetFileHolder.ExtensionLowered); badIsIgnoreExtension = badIsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(badFileHolder.ExtensionLowered); targetIsIgnoreExtension = targetIsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(targetFileHolder.ExtensionLowered); DateTime minimumDateTime = DateTime.ParseExact(Path.GetFileName(minimumDirectory.First()), format, CultureInfo.InvariantCulture, DateTimeStyles.None); DateTime maximumDateTime = DateTime.ParseExact(Path.GetFileName(maximumDirectory.First()), format, CultureInfo.InvariantCulture, DateTimeStyles.None).AddHours(23); (badDateTimeOriginal, badDateTimes, badId, badMessage) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration, _PropertyConfiguration.PopulatePropertyId, badFileHolder, badIsIgnoreExtension, badIsValidImageFormatExtension, asciiEncoding); if (badMessage is not null) throw new Exception(badMessage); if (badDateTimes.Length == 0 || badId is null) throw new Exception(badMessage); (targetDateTimeOriginal, targetDateTimes, targetId, targetMessage) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration, _PropertyConfiguration.PopulatePropertyId, targetFileHolder, targetIsIgnoreExtension, targetIsValidImageFormatExtension, asciiEncoding); if (targetMessage is not null) throw new Exception(targetMessage); if (targetDateTimes.Length == 0 || targetId is null) throw new Exception(targetMessage); if (badDateTimeOriginal is null || targetDateTimeOriginal is null) logger?.LogError("Date is null!"); else { TimeSpan timeSpan = new(targetDateTimeOriginal.Value.Ticks - badDateTimeOriginal.Value.Ticks); DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks); // DateTime a = new(2020, 01, 04, 02, 12, 51, 32); // // DateTime a = new(2020, 01, 05, 18, 17, 15, 97); // DateTime b = new(2020, 01, 05, 19, 52, 30, 17); // DateTime c = new(2024, 12, 07, 11, 19, 06, 13); // // DateTime d = new(2024, 12, 07, 12, 07, 30, 38); // long e = new DateTime(c.Ticks - b.Ticks).AddMinutes(-5).Ticks; // if (a != DateTime.MinValue) // minimumDateTime = a.AddTicks(e).AddHours(-1); // if (c != DateTime.MinValue) // maximumDateTime = c; // DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, e); } } } } } } private List OffsetDateTimeOriginalFilesInDirectories(ILogger? logger) { List results = []; DateFix(logger, _PropertyConfiguration.RootDirectory); return results; } }