using Microsoft.Extensions.Configuration; using Phares.Shared; 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; using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Drag.Drop.Set.Item; public partial class DragDropSetPropertyItem : Form { private record Record(FileHolder FileHolder, bool IsIgnoreExtension, bool IsValidImageFormatExtension, int Id, DateTime? DateTimeOriginal, short? PropertyItemType, string? Value); 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; private readonly Property.Models.Configuration _PropertyConfiguration; public DragDropSetPropertyItem() { InitializeComponent(); AppSettings appSettings; string workingDirectory; IsEnvironment isEnvironment; IConfigurationRoot configurationRoot; 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() .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); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); Property.Models.Configuration.Verify(propertyConfiguration, requireExist: false); _PropertyConfiguration = propertyConfiguration; _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) => _JsonTextBox.Text = message; private List GetRecords(ASCIIEncoding asciiEncoding, int tagId, List files) { List results = []; int? id; string? value; string? message; FileHolder fileHolder; bool isIgnoreExtension; DateTime? dateTimeOriginal; PropertyItem? propertyItem; bool isValidImageFormatExtension; foreach (string file in files) { fileHolder = IFileHolder.Get(file); isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); (dateTimeOriginal, _, 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) continue; using Image image = Image.FromFile(fileHolder.FullName); 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(new(fileHolder, isIgnoreExtension, isValidImageFormatExtension, id.Value, dateTimeOriginal, propertyItem?.Type, value)); } if (files.Count != results.Count) throw new NotSupportedException(); return results; } private void SetPropertyItem(string setTo, int tagId, short type, ASCIIEncoding asciiEncoding, ConstructorInfo constructorInfo, List records) { int? id; Bitmap bitmap; string? message; string checkFile; PropertyItem? propertyItem; foreach (Record record in records) { if (record.PropertyItemType is not null && record.PropertyItemType.Value != type) throw new NotSupportedException(); if ((record.DateTimeOriginal is null || !string.IsNullOrEmpty(record.Value) || record.Value == setTo) && !_PropertyConfiguration.IgnoreRulesKeyWords.Contains(setTo)) continue; checkFile = $"{record.FileHolder.FullName}.exif"; propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, tagId, type, setTo); 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 (id is null || id.Value != record.Id) throw new NotSupportedException(); File.Delete(record.FileHolder.FullName); File.Move(checkFile, record.FileHolder.FullName); } } private void SetPropertyItem(string setTo, List files) { short type = 1; ASCIIEncoding asciiEncoding = new(); int xpKeywords = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinKeywords; ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception(); List records = GetRecords(asciiEncoding, xpKeywords, files); if (records.Count == 0) SetMessage("No data"); else SetPropertyItem(setTo, xpKeywords, type, asciiEncoding, constructorInfo, records); } private void SetPropertyItem(string[] paths, string setTo) { FileInfo fileInfo; List files = []; 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.Count == 0) 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.Length != 0) SetPropertyItem(paths); else { _PathTextBox.Text = string.Empty; SetMessage("No data"); } } catch (Exception) { throw; } } }