using Microsoft.Extensions.Configuration; using Phares.Shared; using Serilog; using System.Diagnostics; using System.Drawing.Imaging; using System.Reflection; using System.Text; using System.Text.Json; using View_by_Distance.Drag.Drop.Set.Item.Models; using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Drag.Drop.Set.Item; public partial class DragDropSetPropertyItem : Form { private readonly ILogger _Logger; private readonly TextBox _PathTextBox; private readonly TextBox _JsonTextBox; private readonly TextBox _FirstTextBox; private readonly AppSettings _AppSettings; private readonly ProgressBar _ProgressBar; private readonly string _WorkingDirectory; private readonly IsEnvironment _IsEnvironment; public DragDropSetPropertyItem() { InitializeComponent(); ILogger logger; AppSettings appSettings; string workingDirectory; IsEnvironment isEnvironment; IConfigurationRoot configurationRoot; LoggerConfiguration loggerConfiguration = new(); Assembly assembly = Assembly.GetExecutingAssembly(); bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true) .AddUserSecrets(); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working path name must have parentDirectory setTo!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); Log.Logger = loggerConfiguration.CreateLogger(); logger = Log.ForContext(); logger.Information("Complete"); _Logger = logger; _AppSettings = appSettings; _IsEnvironment = isEnvironment; _WorkingDirectory = workingDirectory; _ProgressBar = new() { TabIndex = 4, Location = new(5, 5), Dock = DockStyle.Top, Visible = false }; string json = JsonSerializer.Serialize(_AppSettings, new JsonSerializerOptions { WriteIndented = true }); _FirstTextBox = new() { TabIndex = 1, Text = _IsEnvironment.Profile, Location = new(5, 5), Dock = DockStyle.Top }; _PathTextBox = new() { TabIndex = 2, Text = _AppSettings.WorkingDirectoryName, Location = new(5, 5), Dock = DockStyle.Top }; _JsonTextBox = new() { TabIndex = 3, Text = json, Multiline = true, MinimumSize = new(1, 80), Location = new(5, 5), Dock = DockStyle.Top }; Load += new EventHandler(Form1_Load); Controls.Add(_ProgressBar); Controls.Add(_JsonTextBox); Controls.Add(_PathTextBox); Controls.Add(_FirstTextBox); } private void Form1_Load(object? sender, EventArgs e) { try { AllowDrop = true; DragDrop += new DragEventHandler(Form1_DragDrop); DragEnter += new DragEventHandler(Form1_DragEnter); if (_WorkingDirectory is null) { } } catch (Exception) { throw; } } private void Form1_DragEnter(object? sender, DragEventArgs e) { try { if (e.Data is not null && e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; } catch (Exception) { throw; } } private void SetMessage(string message) { _Logger.Information(message); _JsonTextBox.Text = message; } private static List<(string, int, DateTime?, short?, string?)> GetCollection(ASCIIEncoding asciiEncoding, int tagId, List files) { List<(string, int, DateTime?, short?, string?)> results = new(); string? value; PropertyItem? propertyItem; Shared.Models.Property property; foreach (string file in files) { property = Property.Models.A_Property.GetImageProperty(file); if (property.Id is null) continue; using Image image = Image.FromFile(file); if (!image.PropertyIdList.Contains(tagId)) (propertyItem, value) = (null, null); else { propertyItem = image.GetPropertyItem(tagId); if (propertyItem?.Value is null) value = null; else { if (propertyItem.Type == 2) value = asciiEncoding.GetString(propertyItem.Value).Trim('\0', ' '); else if (propertyItem.Type == 1) value = Encoding.Unicode.GetString(propertyItem.Value).Trim('\0', ' '); else value = null; } } results.Add((file, property.Id.Value, property.DateTimeOriginal, propertyItem?.Type, value)); } if (files.Count != results.Count) throw new NotSupportedException(); return results; } private void SetPropertyItem(string setTo, int tagId, short type, ConstructorInfo constructorInfo, List<(string, int, DateTime?, short?, string?)> collection) { Bitmap bitmap; string checkFile; PropertyItem? propertyItem; Shared.Models.Property property; foreach ((string file, int id, DateTime? dateTimeOriginal, short? propertyItemType, string? value) in collection) { if (propertyItemType is not null && propertyItemType.Value != type) throw new NotSupportedException(); if ((dateTimeOriginal is null || !string.IsNullOrEmpty(value) || value == setTo) && !_AppSettings.IgnoreRulesKeyWords.Contains(setTo)) continue; checkFile = $"{file}.exif"; propertyItem = IProperty.GetPropertyItem(constructorInfo, tagId, type, setTo); bitmap = new(file); bitmap.SetPropertyItem(propertyItem); bitmap.Save(checkFile); bitmap.Dispose(); property = Property.Models.A_Property.GetImageProperty(checkFile); if (property.Id is null || property.Id.Value != id) throw new NotSupportedException(); File.Delete(file); File.Move(checkFile, file); } } private void SetPropertyItem(string setTo, List files) { short type = 1; ASCIIEncoding asciiEncoding = new(); int xpKeywords = (int)IExif.Tags.XPKeywords; ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty(), null) ?? throw new Exception(); List<(string, int, DateTime?, short?, string?)> collection = GetCollection(asciiEncoding, xpKeywords, files); if (!collection.Any()) SetMessage("No data"); else SetPropertyItem(setTo, xpKeywords, type, constructorInfo, collection); } private void SetPropertyItem(string[] paths, string setTo) { FileInfo fileInfo; List files = new(); foreach (string path in paths.OrderBy(l => l)) { fileInfo = new(path); if (fileInfo.Exists) files.Add(path); else { if (paths.Length != 1) break; files.AddRange(Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly)); } } if (!files.Any()) SetMessage("No data"); else SetPropertyItem(setTo, files); } private void SetPropertyItem(string[] paths) { if (string.IsNullOrEmpty(_FirstTextBox.Text) || !_AppSettings.ValidKeyWords.Contains(_FirstTextBox.Text)) SetMessage($"[{_FirstTextBox.Text}] is not valid!"); else SetPropertyItem(paths, _FirstTextBox.Text); } private void Form1_DragDrop(object? sender, DragEventArgs e) { try { if (e.Data is not null && e.Data.GetData(DataFormats.FileDrop) is string[] paths && paths.Any()) SetPropertyItem(paths); else { _PathTextBox.Text = string.Empty; SetMessage("No data"); } } catch (Exception) { throw; } } }