using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace DHSoftware.Views
{
    public partial class ImageViewerControl : UserControl
    {
        #region 内部控件
        private PictureBox pictureBox;
        private Label statusLabel;
        #endregion

        #region 核心字段
        private Bitmap _currentImage;
        private float _scale = 1.0f;
        private PointF _offset = PointF.Empty;
        private Point _dragStart;
        private bool _isDragging;
        private readonly object _imageLock = new object();
        #endregion

        #region 公开属性
        public Bitmap Image
        {
            get
            {
                lock (_imageLock)
                {
                    return _currentImage?.Clone() as Bitmap;
                }
            }
            set
            {
                Bitmap newImage = value?.Clone() as Bitmap;
                Bitmap oldImageToDispose = null;

                lock (_imageLock)
                {
                    // 交换图像引用
                    oldImageToDispose = _currentImage;
                    _currentImage = newImage;

                    if (_currentImage != null)
                    {
                        if (oldImageToDispose?.Size != _currentImage.Size)
                        {
                            AutoFit();
                        }
                        else
                        {
                            ClampOffset();
                        }
                    }
                }

                // 在锁外安全释放旧图像
                if (oldImageToDispose != null)
                {
                    // 使用BeginInvoke确保在UI线程释放资源
                    BeginInvoke(new Action(() =>
                    {
                        oldImageToDispose.Dispose();
                        oldImageToDispose = null;
                    }));
                }

                SafeInvalidate();
            }
        }
        #endregion

        public ImageViewerControl()
        {
            InitializeComponents();
            SetupDoubleBuffering();
        }

        #region 初始化
        private void InitializeComponents()
        {
            pictureBox = new PictureBox
            {
                Dock = DockStyle.Fill,
                BackColor = Color.DarkGray,
                Cursor = Cursors.Hand
            };

            statusLabel = new Label
            {
                Dock = DockStyle.Bottom,
                Height = 20,
                Text = "就绪",
                BorderStyle = BorderStyle.FixedSingle,
                Font = new Font("Consolas", 10)
            };

            pictureBox.MouseDown += PictureBox_MouseDown;
            pictureBox.MouseMove += PictureBox_MouseMove;
            pictureBox.MouseUp += PictureBox_MouseUp;
            pictureBox.MouseWheel += PictureBox_MouseWheel;
            pictureBox.Paint += PictureBox_Paint;

            Controls.Add(pictureBox);
            Controls.Add(statusLabel);
        }

        private void SetupDoubleBuffering()
        {
            typeof(PictureBox).GetMethod("SetStyle",
                System.Reflection.BindingFlags.NonPublic |
                System.Reflection.BindingFlags.Instance)?
                .Invoke(pictureBox, new object[] {
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.AllPaintingInWmPaint,
                    true
                });
        }
        #endregion

        #region 核心功能
        private void AutoFit()
        {
            lock (_imageLock)
            {
                if (_currentImage == null) return;

                const float marginRatio = 0.1f;
                float marginWidth = Width * marginRatio;
                float marginHeight = Height * marginRatio;

                _scale = Math.Min(
                    (Width - marginWidth * 2) / _currentImage.Width,
                    (Height - marginHeight * 2) / _currentImage.Height
                );

                _offset.X = marginWidth + (Width - marginWidth * 2 - _currentImage.Width * _scale) / 2;
                _offset.Y = marginHeight + (Height - marginHeight * 2 - _currentImage.Height * _scale) / 2;

                ClampOffset();
            }
        }

        private void PictureBox_Paint(object sender, PaintEventArgs e)
        {
            Bitmap drawImage = null;
            RectangleF destRect;
            float scale;
            PointF offset;

            // 创建临时绘图参数
            lock (_imageLock)
            {
                if (_currentImage == null) return;

                // 创建绘图副本
                drawImage = _currentImage.Clone() as Bitmap;
                scale = _scale;
                offset = _offset;

                destRect = new RectangleF(
                    offset.X,
                    offset.Y,
                    drawImage.Width * scale,
                    drawImage.Height * scale);
            }

            try
            {
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                e.Graphics.DrawImage(drawImage, destRect);
            }
            finally
            {
                drawImage?.Dispose();
            }
        }
        #endregion

        #region 鼠标交互(左键拖动)
        private void PictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (InvokeRequired) return;

            lock (_imageLock)
            {
                if (_currentImage == null) return;

                if (e.Button == MouseButtons.Left)
                {
                    _dragStart = e.Location;
                    _isDragging = true;
                }
            }
        }

        private void PictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (InvokeRequired) return;

            lock (_imageLock)
            {
                if (_currentImage == null) return;

                if (_isDragging)
                {
                    _offset.X += e.X - _dragStart.X;
                    _offset.Y += e.Y - _dragStart.Y;
                    _dragStart = e.Location;
                    ClampOffset();
                    SafeInvalidate();
                }

                UpdateStatus(e.Location);
            }
        }

        private void PictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            lock (_imageLock)
            {
                _isDragging = false;
            }
        }

        private void PictureBox_MouseWheel(object sender, MouseEventArgs e)
        {
            if (InvokeRequired) return;

            lock (_imageLock)
            {
                if (_currentImage == null) return;

                PointF imgPos = ConvertToImageCoords(e.Location);
                if (imgPos.X < 0 || imgPos.X > _currentImage.Width ||
                    imgPos.Y < 0 || imgPos.Y > _currentImage.Height)
                    return;

                float zoom = e.Delta > 0 ? 1.1f : 0.9f;
                float newScale = Math.Clamp(_scale * zoom, 0.1f, 10f);

                _offset.X = e.Location.X - imgPos.X * newScale;
                _offset.Y = e.Location.Y - imgPos.Y * newScale;

                _scale = newScale;
                ClampOffset();
                SafeInvalidate();
            }
        }
        #endregion

        #region 辅助方法
        private PointF ConvertToImageCoords(Point mousePos)
        {
            lock (_imageLock)
            {
                if (_currentImage == null) return PointF.Empty;
                return new PointF(
                    (mousePos.X - _offset.X) / _scale,
                    (mousePos.Y - _offset.Y) / _scale);
            }
        }

        private void ClampOffset()
        {
            lock (_imageLock)
            {
                if (_currentImage == null) return;

                float imgWidth = _currentImage.Width * _scale;
                float imgHeight = _currentImage.Height * _scale;

                _offset.X = Math.Clamp(_offset.X,
                    imgWidth > Width ? Width - imgWidth : 0,
                    imgWidth > Width ? 0 : Width - imgWidth);

                _offset.Y = Math.Clamp(_offset.Y,
                    imgHeight > Height ? Height - imgHeight : 0,
                    imgHeight > Height ? 0 : Height - imgHeight);
            }
        }

        private void UpdateStatus(Point mousePos)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action<Point>(UpdateStatus), mousePos);
                return;
            }

            lock (_imageLock)
            {
                if (_currentImage == null)
                {
                    statusLabel.Text = "无有效图像";
                    return;
                }

                PointF imgPos = ConvertToImageCoords(mousePos);
                bool inImage = imgPos.X >= 0 && imgPos.X <= _currentImage.Width &&
                              imgPos.Y >= 0 && imgPos.Y <= _currentImage.Height;

                statusLabel.Text = inImage ?
                    $"坐标: ({imgPos.X:F1}, {imgPos.Y:F1}) | 缩放: {_scale * 100:0}%" :
                    $"图像尺寸: {_currentImage.Width}x{_currentImage.Height} | 缩放: {_scale * 100:0}%";
            }
        }

        private void SafeInvalidate()
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action(pictureBox.Invalidate));
            }
            else
            {
                pictureBox.Invalidate();
            }
        }
        #endregion

        public Bitmap GetCurrentSnapshot()
        {
            lock (_imageLock)
            {
                // 返回深拷贝防止原始图像被修改
                return _currentImage?.Clone() as Bitmap;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            lock (_imageLock)
            {
                _currentImage?.Dispose();
                _currentImage = null;
            }
            base.Dispose(disposing);
        }
    }
}