using Microsoft.Extensions.Configuration; using Phares.Shared; using Serilog; using System.Diagnostics; using System.Drawing.Imaging; using System.Reflection; using System.Text.Json; using View_by_Distance.Drag_Drop_Explorer.Models; using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless.Methods; using WindowsShortcutFactory; namespace View_by_Distance.Drag_Drop_Explorer; public partial class DragDropMove : 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 DragDropMove() { 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 value!"); 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); _FirstTextBox.LostFocus += new EventHandler(TextBox_LostFocus); _PathTextBox.LostFocus += new EventHandler(TextBox_LostFocus); if (_WorkingDirectory is null) { } } catch (Exception) { throw; } } private static string GetConverted(string value) { string result = value.Length < 2 || value[1] != ':' ? value : value.Replace("\\\\", "/").Replace('\\', '/'); return result; } private void TextBox_LostFocus(object? sender, EventArgs e) { try { if (sender is TextBox textBox) { textBox.Text = GetConverted(textBox.Text); if (textBox.Text == "315360000000000") throw new NotImplementedException(); } } 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 MovePaths(string[] paths) { string file; string checkFile; string? directory; string? relativePath; string[] directories; string? checkDirectory; string? shellDirectory; int rootDirectoryLength; WindowsShortcut windowsShortcut; _PathTextBox.Text = string.Empty; _FirstTextBox.Text = GetConverted(paths[0]); foreach (string path in paths.OrderBy(l => l)) { relativePath = null; shellDirectory = null; if (!path.EndsWith(".lnk")) file = path; else { windowsShortcut = WindowsShortcut.Load(path); if (windowsShortcut.Path is null) continue; file = windowsShortcut.Path; windowsShortcut.Dispose(); } directory = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(directory)) continue; directories = IPath.GetDirectories(directory); foreach (string directoryName in directories) { checkDirectory = $"{directoryName}-Shell"; if (!Directory.Exists(checkDirectory)) continue; shellDirectory = checkDirectory; rootDirectoryLength = directoryName.Length; relativePath = file[rootDirectoryLength..]; break; } if (string.IsNullOrEmpty(shellDirectory) || string.IsNullOrEmpty(relativePath)) continue; checkFile = string.Concat(shellDirectory, relativePath); checkDirectory = Path.GetDirectoryName(checkFile); if (string.IsNullOrEmpty(checkDirectory)) continue; if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); if (File.Exists(checkFile)) continue; File.Move(file, checkFile); } } public static byte[] GetBytes(string value) { byte[] results = new byte[value.Length + 1]; for (int i = 0; i < value.Length; i++) results[i] = (byte)value[i]; results[value.Length] = 0x00; return results; } private static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, string value) { PropertyItem result = (PropertyItem)constructorInfo.Invoke(null); byte[] bytes = GetBytes(value); result.Id = id; result.Len = value.Length + 1; result.Type = 2; result.Value = bytes; return result; } private static List<(string, int, DateTime)> GetCollection(string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks) { List<(string, int, DateTime)> results = new(); DateTime dateTime; Shared.Models.Property property; string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string file in files) { property = Property.Models.A_Property.GetImageProperty(file); if (property.Id is null || property.DateTimeOriginal is null) continue; dateTime = property.DateTimeOriginal.Value.AddTicks(ticks); if (dateTime < minimumDateTime) continue; if (dateTime > maximumDateTime) continue; results.Add((file, property.Id.Value, property.DateTimeOriginal.Value.AddTicks(ticks))); } if (files.Length != results.Count) throw new Exception(); return results; } private static void DateFix(string sourceDirectory, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks) { Bitmap bitmap; string checkFile; PropertyItem? propertyItem; string? ticksDirectory = null; Shared.Models.Property property; int dateTimeOriginal = (int)IExif.Tags.DateTimeOriginal; for (int i = 0; i < int.MaxValue; i++) { ticksDirectory = Path.Combine(sourceDirectory, ticks.ToString()); if (!Directory.Exists(ticksDirectory)) { _ = Directory.CreateDirectory(ticksDirectory); break; } ticks++; } List<(string, int, DateTime)> collection = GetCollection(checkDirectory, minimumDateTime, maximumDateTime, ticks); ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty(), null) ?? throw new Exception(); foreach ((string file, int id, DateTime dateTime) in collection) { if (ticksDirectory is null) throw new Exception(); checkFile = Path.Combine(ticksDirectory, Path.GetFileName(file)); if (File.Exists(checkFile)) continue; propertyItem = GetPropertyItem(constructorInfo, dateTimeOriginal, dateTime.ToString("yyyy:MM:dd HH:mm:ss")); 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 Exception(); } } private void DateFix(string sourceDirectory) { string checkDirectory; long oneYearTicks = DateTime.MinValue.AddYears(1).Ticks; checkDirectory = Path.Combine(sourceDirectory, oneYearTicks.ToString()); if (Directory.Exists(checkDirectory)) DateFix(sourceDirectory, checkDirectory, DateTime.MinValue, DateTime.MaxValue, new TimeSpan(oneYearTicks - DateTime.MinValue.Ticks).Ticks); else { checkDirectory = Path.Combine(sourceDirectory, "1"); if (!Directory.Exists(checkDirectory)) _Logger.Error($"<{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.Error($"<{checkDirectory}> doesn't exist!"); else { string format = "yyyy-MM-dd"; string[] maximumDirectory = Directory.GetDirectories(minimumDirectory.First(), "*", SearchOption.TopDirectoryOnly); string[] badFiles = !Directory.Exists(badDirectory) ? Array.Empty() : Directory.GetFiles(badDirectory, "*", SearchOption.TopDirectoryOnly); string[] targetFiles = !Directory.Exists(targetDirectory) ? Array.Empty() : Directory.GetFiles(targetDirectory, "*", SearchOption.TopDirectoryOnly); if (badFiles.Length != 1 || targetFiles.Length != 1 || maximumDirectory.Length != 1) _Logger.Error("bad file(s) or target file(s) or maximum directory doesn't equal 1!"); else { DateTime minimumDateTime = DateTime.ParseExact(Path.GetFileName(minimumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None); DateTime maximumDateTime = DateTime.ParseExact(Path.GetFileName(maximumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None).AddHours(23); Shared.Models.Property badProperty = Property.Models.A_Property.GetImageProperty(badFiles.First()); Shared.Models.Property targetProperty = Property.Models.A_Property.GetImageProperty(targetFiles.First()); if (badProperty.DateTimeOriginal is null || targetProperty.DateTimeOriginal is null) _Logger.Error("Date is null!"); else { TimeSpan timeSpan = new(targetProperty.DateTimeOriginal.Value.Ticks - badProperty.DateTimeOriginal.Value.Ticks); DateFix(sourceDirectory, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks); } } } } } } 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()) { if (paths.Length == 1 && Directory.Exists(paths.First())) DateFix(paths.First()); else MovePaths(paths); } else { _FirstTextBox.Text = string.Empty; _PathTextBox.Text = string.Empty; _JsonTextBox.Text = string.Empty; _Logger.Information("No data"); } } catch (Exception) { throw; } } }