using EmreIstikam001.component.TehranOffice.ToosForAll;
using Rhino;
using Rhino.Display;
using Rhino.DocObjects;
using Rhino.FileIO;
using Rhino.Geometry;
using Rhino.Runtime.InProcess;
using Rhino.UI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EmreIstikam001.component.TehranOffice.Components.Other.CustomLibrary
{
    public partial class CustomLibraryFrm2 : Form
    {
        public event EventHandler<PictureBoxEventArgs> PictureBoxClicked;
        public event EventHandler<PictureBoxEventArgs> PictureBoxDoubleClicked;

        private volatile bool isCacheReady = false;
        private PictureBox selectedPictureBox;
        public DateTime selectTime = DateTime.Now;
        private List<PictureBox> pictureBoxes = new List<PictureBox>();
        private List<FileInfo> cachedFiles = new List<FileInfo>();
        public string SelectedFilePath { get; private set; } = @"C:\PARDUS_CEPHE_YAZILIMI\Pardus_CY\01_BLOK\01_PROFIL\GENEL_PROFIL_CIZIMLERI\CUHADAROGLU_F_PROFIL.3dm";
        public string FileName { get; private set; }
        public string UserPath { get; private set; }

        int fixedColumnCount = 3;
        int pictureBoxHeightSize = 150;
        int pictureBoxWidthSize = 150;

        private ToolTip toolTip;
        private string initialPath;
        private Timer searchTimer;
        private int currentSearchToken = 0;
        public CustomLibraryFrm2()
        {
            InitializeComponent();
            this.Resize += TableLayoutPanel01_Resize;
            tableLayoutPanel01.Resize += TableLayoutPanel01_Resize;
            initialPath = @"C:\PARDUS_CEPHE_YAZILIMI\Pardus_CY\01_BLOK";

            InitializeGrid();
            toolTip = new ToolTip();
            SetPlaceholder();

            lblSearching.Visible = false;
            pictureBoxSearch.Visible = false;

            // Subscribe to TreeView events
            treeView1.BeforeExpand += TreeView1_BeforeExpand;
            treeView1.AfterSelect += TreeView1_AfterSelect;

            // Initialize ImageList for the TreeView
            InitializeImageList();
            SetPlaceholderLogin();
            // Populate the TreeView
            PopulateTreeView(initialPath);

            // Initialize the search timer (set to 2 seconds)
            searchTimer = new System.Windows.Forms.Timer();
            searchTimer.Interval = 2000; // Set the debounce delay to 2000 milliseconds
            searchTimer.Tick += SearchTimer_Tick;
            // Start building the cache in the background
            Task.Run(() => CacheAllFiles());

        }
        // Resize event handler
        private void TableLayoutPanel01_Resize(object sender, EventArgs e)
        {
            AdjustColumnCount();
        }

        private void AdjustColumnCount()
        {
            // Calculate how many columns can fit in the current width of the TableLayoutPanel
            if (tableLayoutPanel01.Width > 0)
            {
                int availableWidth = tableLayoutPanel01.Width - tableLayoutPanel01.Padding.Horizontal;
                int newColumnCount = Math.Max(1, availableWidth / (pictureBoxWidthSize + tableLayoutPanel01.Margin.Horizontal));

                // Update the TableLayoutPanel and repopulate
                UpdateTableLayout(newColumnCount);
            }
        }

        private void UpdateTableLayout(int newColumnCount)
        {
            // Clear existing data
            tableLayoutPanel01.Controls.Clear();
            tableLayoutPanel01.RowStyles.Clear();
            tableLayoutPanel01.ColumnStyles.Clear();

            if (pictureBoxes.Count == 0) return;

            int rowCount = (int)Math.Ceiling((double)pictureBoxes.Count / newColumnCount);

            tableLayoutPanel01.RowCount = rowCount;
            tableLayoutPanel01.ColumnCount = newColumnCount;

            // Set up styles
            for (int i = 0; i < newColumnCount; i++)
            {
                tableLayoutPanel01.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f / newColumnCount));
            }

            for (int i = 0; i < rowCount; i++)
            {
                tableLayoutPanel01.RowStyles.Add(new RowStyle(SizeType.Absolute, pictureBoxHeightSize));
            }

            tableLayoutPanel01.AutoSize = false;
            tableLayoutPanel01.AutoScroll = true;

            // Add all PictureBoxes back to the panel
            for (int i = 0; i < pictureBoxes.Count; i++)
            {
                int row = i / newColumnCount;
                int col = i % newColumnCount;
                tableLayoutPanel01.Controls.Add(pictureBoxes[i], col, row);
            }
        }

        private void CacheAllFiles()
        {
            DirectoryInfo rootDirectory = new DirectoryInfo(initialPath);

            // Begin caching files
            List<FileInfo> allFiles = new List<FileInfo>();
            GetAllFilesRecursive(rootDirectory, allFiles);

            cachedFiles = allFiles;

            // Set the cache ready flag
            isCacheReady = true;
        }


        /// <summary>
        /// Initializes the ImageList for the TreeView control.
        /// </summary>
        private void InitializeImageList()
        {
            ImageList imageList = new ImageList();

            // Set the desired image size (e.g., 64x64 pixels)
            imageList.ImageSize = new Size(25, 25);

            // Add images to the image list
            imageList.Images.Add("folder", Properties.Resources.noun_folder);  // folder icon
            imageList.Images.Add("file", Properties.Resources.kutuphane);    // file icon
            imageList.Images.Add("file3dm", Properties.Resources.PardusLogo1); // .3dm file icon

            // Assign the ImageList to the TreeView
            treeView1.ImageList = imageList;

            //// Adjust the ItemHeight to accommodate larger images
            //treeView1.ItemHeight = 70;
        }


        /// <summary>
        /// Sets the placeholder text in the search TextBox.
        /// </summary>
        private void SetPlaceholder()
        {
            txtSearch.Text = "search...";
            txtSearch.ForeColor = Color.Gray;
        }
        private void SetPlaceholderLogin()
        {
            txtUser.Text = "Staff ID...";
            txtPass.Text = "Password...";
            txtUser.ForeColor = Color.FromArgb(170, 170, 170);
            txtPass.ForeColor = Color.FromArgb(170, 170, 170);
        }

        /// <summary>
        /// Event handler for when the user enters the search TextBox.
        /// </summary>
        private void txtSearch_Enter(object sender, EventArgs e)
        {
            if (txtSearch.Text == "search...")
            {
                txtSearch.Text = "";
                txtSearch.ForeColor = Color.Black;
            }
        }

        /// <summary>
        /// Event handler for when the user leaves the search TextBox.
        /// </summary>
        private void txtSearch_Leave(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtSearch.Text))
            {
                SetPlaceholder();
            }
        }

        /// <summary>
        /// Initializes the grid layout for displaying thumbnails.
        /// </summary>
        private void InitializeGrid()
        {
            tableLayoutPanel01.RowCount = 3;
            tableLayoutPanel01.ColumnCount = 3;
            tableLayoutPanel01.AutoScroll = true;

            // Set the padding of the TableLayoutPanel
            tableLayoutPanel01.Padding = new Padding(10); // Adjust the padding value as needed
            tableLayoutPanel01.BackColor = Color.White; // Ensure the background is white
        }

        /// <summary>
        /// Populates the TreeView with directories and files from the given root path.
        /// Implements lazy loading for better performance.
        /// </summary>
        private void PopulateTreeView(string rootPath)
        {
            if (!Directory.Exists(rootPath))
            {
                string systemDriveRoot = Path.GetPathRoot(Environment.SystemDirectory);
                string newFolderName = "PARDUS_CEPHE_YAZILIMI";
                string newFolderPath = Path.Combine(systemDriveRoot, newFolderName);

                if (!Directory.Exists(newFolderPath))
                {
                    Directory.CreateDirectory(newFolderPath);
                }

                rootPath = newFolderPath;
            }

            DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);

            TreeNode rootNode = new TreeNode(rootDirectory.Name)
            {
                Tag = rootDirectory,
                ImageKey = "folder"
            };

            // Add a dummy node for lazy loading
            rootNode.Nodes.Add(new TreeNode("Loading..."));
            treeView1.Nodes.Add(rootNode);
            rootNode.Expand();
            //textBox1.Text = rootPath;
        }

        /// <summary>
        /// Event handler for when a TreeView node is about to expand.
        /// Implements lazy loading by loading subdirectories and files at this point.
        /// </summary>
        private void TreeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            TreeNode node = e.Node;

            // Check if node contains a dummy "Loading..." node
            if (node.Nodes.Count == 1 && node.Nodes[0].Text == "Loading...")
            {
                node.Nodes.Clear();

                if (node.Tag is DirectoryInfo dir)
                {
                    GetDirectories(dir, node);
                }
            }
        }

        /// <summary>
        /// Recursively adds subdirectories and files to the TreeView node.
        /// </summary>
        private void GetDirectories(DirectoryInfo dir, TreeNode nodeToAddTo)
        {
            try
            {
                // Add subdirectories
                DirectoryInfo[] subDirs = dir.GetDirectories();

                foreach (DirectoryInfo subDir in subDirs)
                {
                    TreeNode subNode = new TreeNode(subDir.Name)
                    {
                        Tag = subDir,
                        ImageKey = "folder"
                    };
                    // Add a dummy node for lazy loading
                    subNode.Nodes.Add(new TreeNode("Loading..."));
                    nodeToAddTo.Nodes.Add(subNode);
                }

                // Add files
                FileInfo[] files = dir.GetFiles();
                foreach (FileInfo file in files)
                {
                    TreeNode fileNode = new TreeNode(file.Name)
                    {
                        Tag = file,
                        ImageKey = file.Extension.Equals(".3dm", StringComparison.OrdinalIgnoreCase) ? "file3dm" : "file"
                    };
                    nodeToAddTo.Nodes.Add(fileNode);
                }
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine($"Access denied to {dir.FullName}: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred accessing {dir.FullName}: {ex.Message}");
            }
        }

        /// <summary>
        /// Event handler for when a node in the TreeView is selected.
        /// </summary>
        private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            var selectedNode = e.Node;
            FileName = selectedNode.Text;

            if (selectedNode.Tag is DirectoryInfo selectedDirectory)
            {
                pictureBoxes.Clear();
                PopulateTableWithThumbnails(selectedDirectory);
            }
            else if (selectedNode.Tag is FileInfo selectedFile)
            {
                SelectedFilePath = selectedFile.FullName;

                // Clear existing controls
                pictureBoxes.Clear();
                tableLayoutPanel01.Controls.Clear();
                tableLayoutPanel01.RowStyles.Clear();
                tableLayoutPanel01.ColumnStyles.Clear();

                tableLayoutPanel01.RowCount = 0;
                tableLayoutPanel01.ColumnCount = 0;

                tableLayoutPanel01.RowCount = 1;
                tableLayoutPanel01.ColumnCount = 1;

                tableLayoutPanel01.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
                tableLayoutPanel01.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));

                // Create the PictureBox
                PictureBox pictureBox = new PictureBox
                {
                    Width = 1300,
                    Height = 1500,
                    SizeMode = PictureBoxSizeMode.Zoom,
                    Anchor = AnchorStyles.None,
                    Margin = new Padding(0),
                    Tag = selectedFile.FullName,
                    Cursor = Cursors.Hand,


                };

                // Load the thumbnail
                try
                {
                    Bitmap rhinoThumbnail = WindowsThumbnailProvider.GetThumbnail(selectedFile.FullName, 400, 600, ThumbnailOptions.InCacheOnly);
                    if (rhinoThumbnail != null)
                    {
                        pictureBox.Image = rhinoThumbnail;
                    }
                    else
                    {
                        // If no thumbnail is available, you can display a placeholder image
                        // pictureBox.Image = Properties.Resources.PlaceholderImage;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error loading thumbnail for {selectedFile.FullName}: {ex.Message}");
                    // Optionally display an error image
                    // pictureBox.Image = Properties.Resources.ErrorImage;
                }

                // Add the PictureBox to the tableLayoutPanel in the center cell
                tableLayoutPanel01.Controls.Add(pictureBox, 0, 0);

                pictureBoxes.Add(pictureBox);
            }

            // Remove existing event handlers to prevent multiple subscriptions
            foreach (Control control in tableLayoutPanel01.Controls)
            {
                if (control is PictureBox pictureBox)
                {
                    pictureBox.Click += PictureBox_Click;

                    pictureBox.Paint += PictureBox_Paint;
                }
            }
        }

        /// <summary>
        /// Event handler for the "Browse" button click to select a custom directory.
        /// </summary>
        private void button1_Click(object sender, EventArgs e)
        {
            if (fbd1.ShowDialog() == DialogResult.OK)
            {
                UserPath = fbd1.SelectedPath;
                treeView1.Nodes.Clear();
                PopulateTreeView(UserPath);
            }
        }

        /// <summary>
        /// Populates the TableLayoutPanel with thumbnails of the files in the given directory.
        /// </summary>
        public void PopulateTableWithThumbnails(DirectoryInfo directory)
        {
            // Clear existing data
            pictureBoxes.Clear();
            tableLayoutPanel01.Controls.Clear();
            tableLayoutPanel01.RowStyles.Clear();
            tableLayoutPanel01.ColumnStyles.Clear();

            tableLayoutPanel01.RowCount = 0;
            tableLayoutPanel01.ColumnCount = 0;

            // Begin layout suspension
            tableLayoutPanel01.SuspendLayout();

            
            // Get files with .3dm extension
            FileInfo[] files = directory.GetFiles()
                .Where(f => f.Extension.Equals(".3dm", StringComparison.OrdinalIgnoreCase))
                .ToArray();

            int rowCount = (int)Math.Ceiling((double)files.Length / fixedColumnCount);

            tableLayoutPanel01.RowCount = rowCount;
            tableLayoutPanel01.ColumnCount = fixedColumnCount;

            // Set up styles
            for (int i = 0; i < fixedColumnCount; i++)
            {
                tableLayoutPanel01.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f / fixedColumnCount));
            }

            for (int i = 0; i < rowCount; i++)
            {
                tableLayoutPanel01.RowStyles.Add(new RowStyle(SizeType.Absolute, pictureBoxWidthSize));
            }

            tableLayoutPanel01.AutoSize = false;
            tableLayoutPanel01.AutoScroll = true;

            // Populate controls
            for (int i = 0; i < files.Length; i++)
            {
                FileInfo file = files[i];
                PictureBox pictureBox = CreatePictureBoxForFile(file, pictureBoxWidthSize, pictureBoxHeightSize);

                int row = i / fixedColumnCount;
                int col = i % fixedColumnCount;
                tableLayoutPanel01.Controls.Add(pictureBox, col, row);
                pictureBoxes.Add(pictureBox);
            }

            // End layout suspension and refresh
            tableLayoutPanel01.ResumeLayout();
            tableLayoutPanel01.Refresh();
        }

        /// <summary>
        /// Creates a PictureBox for the given file.
        /// </summary>
        private PictureBox CreatePictureBoxForFile(FileInfo file, int pictureBoxWidth, int pictureBoxHeight)
        {
            PictureBox pictureBox = new PictureBox
            {
                Width = pictureBoxWidth,
                Height = pictureBoxHeight,
                BorderStyle = BorderStyle.None,
                SizeMode = PictureBoxSizeMode.StretchImage,
                Cursor = Cursors.Hand,
                BackColor = Color.LightGray,
                Tag = file.FullName,
                Margin = new Padding(5) // Adjust the margin value as needed
            };


            toolTip.SetToolTip(pictureBox, file.Name);

            // Load thumbnail image
            try
            {
                //Bitmap rhinoThumbnail = WindowsThumbnailProvider.GetThumbnail(file.FullName, pictureBoxWidth, pictureBoxHeight, ThumbnailOptions.InCacheOnly);
                Bitmap rhinoThumbnail = File3dm.ReadPreviewImage(file.FullName);
                if (rhinoThumbnail != null)
                {
                    pictureBox.Image = rhinoThumbnail;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error loading thumbnail for {file.FullName}: {ex.Message}");
            }

            return pictureBox;
        }

        /// <summary>
        /// Click event handler for PictureBox.
        /// </summary>
        private void PictureBox_Click(object sender, EventArgs e)
        {
            if (sender is PictureBox clickedPictureBox)
            {
                if ((DateTime.Now.Ticks - selectTime.Ticks) / 10000 < 300 && selectedPictureBox == clickedPictureBox)
                {
                    //PictureBox_DoubleClick(sender, e);
                    // Raise the custom event
                    SelectedFilePath = clickedPictureBox.Tag.ToString();
                    FileName = Path.GetFileNameWithoutExtension(clickedPictureBox.Tag.ToString());
                    OnPictureBoxClicked(clickedPictureBox);
                }
                selectTime = DateTime.Now;
                if (selectedPictureBox != null)
                {
                    selectedPictureBox.BorderStyle = BorderStyle.None;
                    selectedPictureBox.Invalidate();
                }

                selectedPictureBox = clickedPictureBox;

                selectedPictureBox.BorderStyle = BorderStyle.FixedSingle;
                selectedPictureBox.Invalidate();
            }
        }

        /// <summary>
        /// Double-click event handler for PictureBox.
        /// </summary>
        private void PictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (sender is PictureBox doubleClickedPictureBox)
            {
                SelectedFilePath = doubleClickedPictureBox.Tag.ToString();
                // Raise the custom event
                //OnPictureBoxDoubleClicked(doubleClickedPictureBox);
            }

        }

        protected virtual void OnPictureBoxDoubleClicked(PictureBox clickedPictureBox)
        {
            PictureBoxDoubleClicked?.Invoke(this, new PictureBoxEventArgs(clickedPictureBox));
        }


        protected virtual void OnPictureBoxClicked(PictureBox clickedPictureBox)
        {
            PictureBoxClicked?.Invoke(this, new PictureBoxEventArgs(clickedPictureBox));
        }




        /// <summary>
        /// Paint event handler for PictureBox to draw a border around the selected PictureBox.
        /// </summary>
        private void PictureBox_Paint(object sender, PaintEventArgs e)
        {
            if (sender is PictureBox picBox && picBox == selectedPictureBox)
            {
                var borderWidth = 10;
                var borderColor = Color.CadetBlue;

                Rectangle rect = new Rectangle(0, 0, picBox.Width - 3, picBox.Height - 3);

                using (Pen pen = new Pen(borderColor, borderWidth))
                {
                    e.Graphics.DrawRectangle(pen, rect);
                }
            }
        }

        private async void SearchTimer_Tick(object sender, EventArgs e)
        {
            // Stop the timer
            searchTimer.Stop();

            // Capture the current search token
            int searchToken = currentSearchToken;

            // Perform the search asynchronously
            await PerformSearchAsync(searchToken);
        }

        private async Task PerformSearchAsync(int searchToken)
        {
            // Ensure we're on the UI thread before updating UI controls
            if (InvokeRequired)
            {
                Invoke(new Action(async () => await PerformSearchAsync(searchToken)));
                return;
            }

            // Show the searching indicators
            lblSearching.Visible = true;
            pictureBoxSearch.Visible = true;

            string searchText = txtSearch.Text.ToLower();
            bool searchSubdirectories = chbSearchAll.Checked;
            List<FileInfo> matchingFiles = null;

            
            if (searchSubdirectories)
            {
                if (!isCacheReady)
                {
                    // Cache is not ready
                    lblSearching.Text = "Building file cache, please wait...";
                    return;
                }

                // Perform search in the cache list on a background thread
                matchingFiles = await Task.Run(() =>
                {
                    return cachedFiles.Where(file => file.Name.ToLower().Contains(searchText)).ToList();
                });
            }
            else
            {
                DirectoryInfo currentDirectory = GetCurrentSelectedDirectory();

                if (currentDirectory == null)
                {
                    // Remove "Searching..." label
                    tableLayoutPanel01.Controls.Clear();

                    // Only hide the indicators if this is the latest search
                    if (searchToken == currentSearchToken)
                    {
                        lblSearching.Visible = false;
                        pictureBoxSearch.Visible = false;
                    }
                    return;
                }

                // Perform search in current directory on a background thread
                matchingFiles = await Task.Run(() =>
                {
                    return SearchInCurrentDirectory(currentDirectory, searchText);
                });
            }

            // Before updating the UI, check if this is still the latest search
            if (searchToken != currentSearchToken)
            {
                // A newer search has started, do not update the UI or hide the indicators
                return;
            }

            // Update the UI with the matching files
            UpdatePictureBoxes(matchingFiles, searchToken);

            // Hide the searching indicators
            lblSearching.Visible = false;
            pictureBoxSearch.Visible = false;
        }

        private DirectoryInfo GetCurrentSelectedDirectory()
        {
            if (treeView1.SelectedNode?.Tag is DirectoryInfo dir)
            {
                return dir;
            }
            else if (treeView1.SelectedNode?.Tag is FileInfo file)
            {
                return file.Directory;
            }
            else
            {
                return null;
            }
        }
        // Recursive method to get all files
        private void GetAllFilesRecursive(DirectoryInfo directory, List<FileInfo> allFiles)
        {
            try
            {
                allFiles.AddRange(directory.GetFiles()
                    .Where(file => file.Extension.Equals(".3dm", StringComparison.OrdinalIgnoreCase)));

                foreach (DirectoryInfo subDir in directory.GetDirectories())
                {
                    GetAllFilesRecursive(subDir, allFiles);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error accessing {directory.FullName}: {ex.Message}");
            }
        }

        private void ResetPictureBoxesToCurrentDirectory()
        {
            if (treeView1.SelectedNode?.Tag is DirectoryInfo selectedDirectory)
            {
                pictureBoxes.Clear();
                PopulateTableWithThumbnails(selectedDirectory);
            }
            else if (treeView1.SelectedNode?.Tag is FileInfo selectedFile)
            {
                pictureBoxes.Clear();
                PopulateTableWithThumbnails(selectedFile.Directory);
            }
            else
            {
                // Handle case when nothing is selected
                pictureBoxes.Clear();
                tableLayoutPanel01.Controls.Clear();
            }
        }

        /// <summary>
        /// Event handler for text changes in the search TextBox.
        /// </summary>
        private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            string searchText = txtSearch.Text.ToLower();

            if (searchText == "search..." || string.IsNullOrWhiteSpace(searchText))
            {
                // Reset the displayed PictureBoxes
                ResetPictureBoxesToCurrentDirectory();

                // Optionally, reset the search token
                // currentSearchToken = 0;

                return;
            }

            if (chbSearchAll.Checked && !isCacheReady)
            {
                // Show a message indicating that cache is being built
                lblSearching.Text = "Building file cache, please wait...";
                lblSearching.Visible = true;
                pictureBoxSearch.Visible = true;

                // Do not proceed with search until cache is ready
                return;
            }

            // Clear the tableLayoutPanel01
            tableLayoutPanel01.Controls.Clear();

            lblSearching.Text = "Searching...";
            lblSearching.Visible = true;
            pictureBoxSearch.Visible = true;

            // Increment the search token
            currentSearchToken++;

            // Restart the timer for debouncing
            searchTimer.Stop();
            searchTimer.Start();
        }

        /// <summary>
        /// Searches for files containing the search text in the current directory.
        /// </summary>
        // Search only in the current directory
        private List<FileInfo> SearchInCurrentDirectory(DirectoryInfo directory, string searchText)
        {
            try
            {
                var matchingFiles = directory.GetFiles()
                    .Where(file => file.Name.ToLower().Contains(searchText) &&
                                   file.Extension.Equals(".3dm", StringComparison.OrdinalIgnoreCase))
                    .ToList();
                return matchingFiles;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred during search: {ex.Message}");
                return new List<FileInfo>();
            }
        }

        /// <summary>
        /// Searches for files containing the search text recursively in all subdirectories.
        /// </summary>
        // Search recursively through all subdirectories
        private List<FileInfo> SearchInAllDirectories(DirectoryInfo directory, string searchText)
        {
            List<FileInfo> matchingFiles = new List<FileInfo>();
            GetMatchingFilesRecursive(directory, searchText, matchingFiles);

            //UpdatePictureBoxes(matchingFiles);
            return matchingFiles;
        }


        /// <summary>
        /// Recursively gets matching files containing the search text.
        /// </summary>
        // Recursive method to get all matching files
        private void GetMatchingFilesRecursive(DirectoryInfo directory, string searchText, List<FileInfo> matchingFiles)
        {
            try
            {
                matchingFiles.AddRange(directory.GetFiles()
                    .Where(file => file.Name.ToLower().Contains(searchText) &&
                                   file.Extension.Equals(".3dm", StringComparison.OrdinalIgnoreCase)));

                foreach (DirectoryInfo subDir in directory.GetDirectories())
                {
                    GetMatchingFilesRecursive(subDir, searchText, matchingFiles);
                }
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine($"Access denied to directory: {directory.FullName}, {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred accessing {directory.FullName}: {ex.Message}");
            }
        }

        /// <summary>
        /// Updates the PictureBox controls with the matching files.
        /// </summary>
        // Updates the PictureBox controls with the matching files
        private void UpdatePictureBoxes(List<FileInfo> matchingFiles, int searchToken)
        {
            if (searchToken != currentSearchToken)
            {
                // A newer search has started, do not update the UI
                return;
            }

            if (InvokeRequired)
            {
                Invoke(new Action(() => UpdatePictureBoxes(matchingFiles, searchToken)));
                return;
            }

            lblSearching.Visible = false;
            pictureBoxSearch.Visible = false;

            // Clear existing controls and styles
            pictureBoxes.Clear();
            tableLayoutPanel01.Controls.Clear();
            tableLayoutPanel01.RowStyles.Clear();
            tableLayoutPanel01.ColumnStyles.Clear();
            tableLayoutPanel01.RowCount = 0;
            tableLayoutPanel01.ColumnCount = 0;

            // Begin layout suspension
            tableLayoutPanel01.SuspendLayout();

            if (matchingFiles.Count == 0)
            {
                // Display "No files found" message
                tableLayoutPanel01.RowCount = 1;
                tableLayoutPanel01.ColumnCount = 1;
                tableLayoutPanel01.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
                tableLayoutPanel01.RowStyles.Add(new RowStyle(SizeType.Percent, 100));

                Label noResultsLabel = new Label()
                {
                    Text = "No files found.",
                    AutoSize = true,
                    Dock = DockStyle.Fill,
                    TextAlign = ContentAlignment.MiddleCenter
                };
                tableLayoutPanel01.Controls.Add(noResultsLabel, 0, 0);
            }
            else
            {
                
                

                int rowCount = (int)Math.Ceiling((double)matchingFiles.Count / fixedColumnCount);

                tableLayoutPanel01.RowCount = rowCount;
                tableLayoutPanel01.ColumnCount = fixedColumnCount;

                // Set up styles
                for (int i = 0; i < fixedColumnCount; i++)
                {
                    tableLayoutPanel01.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f / fixedColumnCount));
                }

                for (int i = 0; i < rowCount; i++)
                {
                    tableLayoutPanel01.RowStyles.Add(new RowStyle(SizeType.Absolute, pictureBoxWidthSize));
                }

                tableLayoutPanel01.AutoSize = false;
                tableLayoutPanel01.AutoScroll = true;

                // Populate controls
                for (int i = 0; i < matchingFiles.Count; i++)
                {
                    FileInfo file = matchingFiles[i];
                    PictureBox pictureBox = CreatePictureBoxForFile(file, pictureBoxWidthSize, pictureBoxHeightSize);

                    int row = i / fixedColumnCount;
                    int col = i % fixedColumnCount;
                    tableLayoutPanel01.Controls.Add(pictureBox, col, row);
                    pictureBoxes.Add(pictureBox);
                }
            }

            // Remove existing event handlers to prevent multiple subscriptions
            foreach (Control control in tableLayoutPanel01.Controls)
            {
                if (control is PictureBox pictureBox)
                {
                    pictureBox.Click += PictureBox_Click;

                    pictureBox.Paint += PictureBox_Paint;
                }
            }

            // End layout suspension and refresh
            tableLayoutPanel01.ResumeLayout();
            tableLayoutPanel01.Refresh();
        }

        /// <summary>
        /// Custom event arguments for PictureBox events.
        /// </summary>
        public class PictureBoxEventArgs : EventArgs
        {
            public PictureBox ClickedPictureBox { get; set; }

            public PictureBoxEventArgs(PictureBox pictureBox)
            {
                ClickedPictureBox = pictureBox;
            }
        }



        private void txtUser_Enter(object sender, EventArgs e)
        {
            if (txtUser.Text == "Staff ID...")
            {
                txtUser.Text = "";
                txtUser.ForeColor = Color.FromArgb(86, 106, 127);
            }
        }

        private void txtUser_Leave(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtUser.Text))
            {
                txtUser.Text = "Staff ID...";
                txtUser.ForeColor = Color.FromArgb(170, 170, 170);
            }
        }


        private void txtPass_Enter(object sender, EventArgs e)
        {
            if (txtPass.Text == "Password...")
            {
                txtPass.Text = "";
                txtPass.ForeColor = Color.FromArgb(86, 106, 127);
            }
        }

        private void txtPass_Leave(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtPass.Text))
            {
                txtPass.Text = "Password...";
                txtPass.ForeColor = Color.FromArgb(170, 170, 170);
            }
        }

        private void lblSearching_Click(object sender, EventArgs e)
        {

        }

     
    }
}

this is my form code, iss it possible to create the treeview from the ThumbnailDatabase.xml but only the Folderss should be in the tree view, and after selecting every node of the tree view all the images in that folder generates from the base64 in the xml file?