using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Drag_Drop.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;

namespace View_by_Distance.Drag_Drop;

public partial class DragDropSearch : Form
{

    private readonly TextBox _TextBox;
    private readonly AppSettings _AppSettings;
    private readonly ProgressBar _ProgressBar;
    private readonly string _WorkingDirectory;
    private readonly IsEnvironment _IsEnvironment;
    private readonly Dictionary<int, Item> _IdToItem;
    private readonly string _ResizeFileNameExtension;
    private readonly Models.Configuration _Configuration;
    private readonly IConfigurationRoot _ConfigurationRoot;
    private readonly Property.Models.Configuration _PropertyConfiguration;

    public DragDropSearch()
    {
        InitializeComponent();
        _IdToItem = [];
        AppSettings appSettings;
        string workingDirectory;
        IsEnvironment isEnvironment;
        Models.Configuration configuration;
        IConfigurationRoot configurationRoot;
        Property.Models.Configuration propertyConfiguration;
        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(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
            .AddUserSecrets<Program>();
        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);
        propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
        configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
        (_, _, string resizeFileNameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality);
        _AppSettings = appSettings;
        _Configuration = configuration;
        _IsEnvironment = isEnvironment;
        _WorkingDirectory = workingDirectory;
        _ConfigurationRoot = configurationRoot;
        _PropertyConfiguration = propertyConfiguration;
        _ResizeFileNameExtension = resizeFileNameExtension;
        _TextBox = new() { Location = new(5, 5), Dock = DockStyle.Top };
        _ProgressBar = new() { Location = new(5, 5), Dock = DockStyle.Top, Visible = false };
        Load += new EventHandler(Form1_Load);
        Controls.Add(_ProgressBar);
        Controls.Add(_TextBox);
    }

    void Form1_Load(object? sender, EventArgs e)
    {
        try
        {
            AllowDrop = true;
            DragDrop += new DragEventHandler(Form1_DragDrop);
            DragEnter += new DragEventHandler(Form1_DragEnter);
            _TextBox.LostFocus += new EventHandler(TextBox_LostFocus);
        }
        catch (Exception)
        {
            throw;
        }
    }

    void TextBox_LostFocus(object? sender, EventArgs e)
    {
        try
        {
            if (_TextBox.Text == "ps")
                throw new NotImplementedException();
        }
        catch (Exception)
        {
            throw;
        }
    }

    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;
        }
    }

    void LoadData()
    {
        Container[] containers;
        string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
        (_, containers) = IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
        List<Item> collection = Program.GetItemCollection(_Configuration, containers);
        foreach (Item item in collection)
        {
            if (item.Property?.Id is null)
                continue;
            if (_IdToItem.ContainsKey(item.Property.Id.Value))
                continue;
            _IdToItem.Add(item.Property.Id.Value, item);
        }
    }

    public static string? GetFaceEncoding(string file)
    {
        string? result;
        List<string> results = [];
        const string comment = "Comment: ";
        if (File.Exists(file))
        {
            IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
            foreach (MetadataExtractor.Directory directory in directories)
            {
                if (directory.Name != "PNG-tEXt")
                    continue;
                foreach (MetadataExtractor.Tag tag in directory.Tags)
                {
                    if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
                        continue;
                    if (!tag.Description.StartsWith(comment))
                        continue;
                    results.Add(tag.Description);
                }
            }
        }
        result = results.Count != 0 ? results[0][comment.Length..] : null;
        return result;
    }

    private void GetDirectoriesOrDoDragDrop(string[] paths)
    {
        string name;
        string[] segments;
        foreach (string path in paths)
        {
            name = Path.GetFileNameWithoutExtension(path);
            Text = name;
            segments = name.Split('.');
            if (_IdToItem.Count == 0)
                LoadData();
            if (int.TryParse(segments[0], out int id) && _IdToItem.TryGetValue(id, out Item? item))
            {
                Text = item.ImageFileHolder.Name;
                _TextBox.Text = item.ImageFileHolder.FullName;
                if (!string.IsNullOrEmpty(item.ImageFileHolder.DirectoryName))
                    _ = Process.Start("explorer.exe", string.Concat("\"", item.ImageFileHolder.DirectoryName, "\""));
            }
        }
    }

    void Form1_DragDrop(object? sender, DragEventArgs e)
    {
        try
        {
            if (e.Data is null || e.Data.GetData(DataFormats.FileDrop) is not string[] paths)
                _TextBox.Text = string.Empty;
            else
                GetDirectoriesOrDoDragDrop(paths);
        }
        catch (Exception)
        {
            throw;
        }
    }

}