using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace Hawkeye.VisionBuilder.Features.ImagesStrip.Components
{
    /// <summary>
    /// A virtualized image list control that efficiently displays image thumbnails
    /// by loading only the images in the current window (managed by ImagesViewModel).
    /// </summary>
    public partial class VirtualizedImageList : UserControl
    {
        private ImagesViewModel _viewModel;
        private Dictionary<int, ImageThumbnailControl> _thumbnailControls = new Dictionary<int, ImageThumbnailControl>();
        private bool _isUpdating = false;

        /// <summary>
        /// Gets or sets the ImagesViewModel that manages the image data and windowing logic.
        /// </summary>
        public ImagesViewModel ViewModel
        {
            get => _viewModel;
            set
            {
                if (_viewModel != null)
                {
                    // Unsubscribe from old view model
                    _viewModel.ImagesAdded -= OnImagesAdded;
                    _viewModel.ImagesRemoved -= OnImagesRemoved;
                    _viewModel.CurrentImageChanged -= OnCurrentImageChanged;
                    _viewModel.ImagesCleared -= OnImagesCleared;
                }

                _viewModel = value;

                if (_viewModel != null)
                {
                    // Subscribe to new view model
                    _viewModel.ImagesAdded += OnImagesAdded;
                    _viewModel.ImagesRemoved += OnImagesRemoved;
                    _viewModel.CurrentImageChanged += OnCurrentImageChanged;
                    _viewModel.ImagesCleared += OnImagesCleared;

                    // Load initial images
                    RefreshImages();
                }
            }
        }

        /// <summary>
        /// Event raised when a thumbnail is clicked by the user.
        /// </summary>
        public event EventHandler<string> ImageSelected;

        public VirtualizedImageList()
        {
            InitializeComponent();
        }

        private void OnImagesAdded(object sender, ImageAddedEventArgs[] e)
        {
            if (_isUpdating) return;

            _isUpdating = true;
            flowLayoutPanel.SuspendLayout();

            try
            {
                foreach (var args in e.OrderBy(x => x.Index))
                {
                    AddThumbnail(args.Index, args.FilePath);
                }
            }
            finally
            {
                flowLayoutPanel.ResumeLayout();
                _isUpdating = false;
            }

            UpdateCurrentSelection();
        }

        private void OnImagesRemoved(object sender, ImageRemovedEventArgs[] e)
        {
            if (_isUpdating) return;

            _isUpdating = true;
            flowLayoutPanel.SuspendLayout();

            try
            {
                foreach (var args in e.OrderByDescending(x => x.Index))
                {
                    RemoveThumbnail(args.Index);
                }
            }
            finally
            {
                flowLayoutPanel.ResumeLayout();
                _isUpdating = false;
            }
        }

        private void OnCurrentImageChanged(object sender, CurrentImageChangedEventArgs e)
        {
            UpdateCurrentSelection();
            ScrollToCurrentImage();
        }

        private void OnImagesCleared(object sender, EventArgs e)
        {
            ClearAllThumbnails();
        }

        private void AddThumbnail(int index, string filePath)
        {
            // Create new thumbnail control
            var thumbnail = new ImageThumbnailControl
            {
                ImagePath = filePath,
                Tag = index // Store the index in Tag for later reference
            };

            thumbnail.ThumbnailClicked += OnThumbnailClicked;

            // Find the correct insertion position to maintain order
            int insertPosition = 0;
            foreach (Control control in flowLayoutPanel.Controls)
            {
                if (control.Tag is int controlIndex && controlIndex < index)
                {
                    insertPosition++;
                }
                else
                {
                    break;
                }
            }

            flowLayoutPanel.Controls.Add(thumbnail);
            flowLayoutPanel.Controls.SetChildIndex(thumbnail, insertPosition);
            _thumbnailControls[index] = thumbnail;
        }

        private void RemoveThumbnail(int index)
        {
            if (_thumbnailControls.TryGetValue(index, out var thumbnail))
            {
                thumbnail.ThumbnailClicked -= OnThumbnailClicked;
                flowLayoutPanel.Controls.Remove(thumbnail);
                thumbnail.Dispose();
                _thumbnailControls.Remove(index);
            }
        }

        private void ClearAllThumbnails()
        {
            _isUpdating = true;
            flowLayoutPanel.SuspendLayout();

            try
            {
                foreach (var thumbnail in _thumbnailControls.Values)
                {
                    thumbnail.ThumbnailClicked -= OnThumbnailClicked;
                    thumbnail.Dispose();
                }

                _thumbnailControls.Clear();
                flowLayoutPanel.Controls.Clear();
            }
            finally
            {
                flowLayoutPanel.ResumeLayout();
                _isUpdating = false;
            }
        }

        private void UpdateCurrentSelection()
        {
            if (_viewModel == null) return;

            int currentIndex = _viewModel.CurrentIndex;

            // Update IsSelected property for all thumbnails
            foreach (var kvp in _thumbnailControls)
            {
                kvp.Value.IsSelected = (kvp.Key == currentIndex);
            }

            // Raise event for external listeners
            if (_thumbnailControls.TryGetValue(currentIndex, out var currentThumbnail))
            {
                ImageSelected?.Invoke(this, currentThumbnail.ImagePath);
            }
        }

        private void ScrollToCurrentImage()
        {
            if (_viewModel == null) return;

            int currentIndex = _viewModel.CurrentIndex;

            if (_thumbnailControls.TryGetValue(currentIndex, out var thumbnail))
            {
                // Scroll the thumbnail into view
                flowLayoutPanel.ScrollControlIntoView(thumbnail);
            }
        }

        private void OnThumbnailClicked(object sender, EventArgs e)
        {
            if (sender is ImageThumbnailControl thumbnail && _viewModel != null)
            {
                string imagePath = thumbnail.ImagePath;

                // Notify view model of selection
                _viewModel.SelectByPath(imagePath);

                // Raise event for external listeners
                ImageSelected?.Invoke(this, imagePath);
            }
        }

        private void RefreshImages()
        {
            if (_viewModel == null) return;

            ClearAllThumbnails();

            _isUpdating = true;
            flowLayoutPanel.SuspendLayout();

            try
            {
                // Add all currently loaded images
                foreach (var imageItem in _viewModel.LoadedImages.OrderBy(x => x.Index))
                {
                    AddThumbnail(imageItem.Index, imageItem.FilePath);
                }
            }
            finally
            {
                flowLayoutPanel.ResumeLayout();
                _isUpdating = false;
            }

            UpdateCurrentSelection();
            ScrollToCurrentImage();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_viewModel != null)
                {
                    _viewModel.ImagesAdded -= OnImagesAdded;
                    _viewModel.ImagesRemoved -= OnImagesRemoved;
                    _viewModel.CurrentImageChanged -= OnCurrentImageChanged;
                    _viewModel.ImagesCleared -= OnImagesCleared;
                }

                ClearAllThumbnails();
            }

            base.Dispose(disposing);
        }
    }
}
