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

namespace AGVMapEditor.Controls
{
    /// <summary>
    /// 이미지 편집용 사용자 정의 캔버스 컨트롤
    /// 이미지 중앙 정렬, 크기 조정 핸들, 브러시 그리기 기능 제공
    /// </summary>
    public class ImageEditorCanvas : UserControl
    {
        private Bitmap _editingImage;
        private Graphics _imageGraphics;
        private Rectangle _imageRect = Rectangle.Empty;
        private float _imageDisplayWidth = 0;
        private float _imageDisplayHeight = 0;

        // 브러시 그리기
        private bool _isDrawing = false;
        private Point _lastDrawPoint = Point.Empty;
        private Color _drawColor = Color.Black;
        private int _brushSize = 3;
        private bool _brushModeEnabled = false;

        // 크기 조정
        private bool _isResizing = false;
        private ResizeHandle _activeHandle = ResizeHandle.None;
        private Point _resizeStartPoint = Point.Empty;
        private float _resizeStartWidth = 0;
        private float _resizeStartHeight = 0;
        private const int HANDLE_SIZE = 8;

        private enum ResizeHandle
        {
            None,
            TopLeft, Top, TopRight,
            Right, BottomRight, Bottom,
            BottomLeft, Left
        }

        public ImageEditorCanvas()
        {
            this.DoubleBuffered = true;
            this.BackColor = Color.White;
            this.AutoScroll = true;

            
        }

        #region Properties

        public Bitmap EditingImage
        {
            get => _editingImage;
            set
            {
                _editingImage = value;
                if (_editingImage != null)
                {
                    _imageGraphics?.Dispose();
                    _imageGraphics = Graphics.FromImage(_editingImage);
                    _imageDisplayWidth = _editingImage.Width;
                    _imageDisplayHeight = _editingImage.Height;
                    UpdateImageRect();
                }
                Invalidate();
            }
        }

        public Color DrawColor
        {
            get => _drawColor;
            set => _drawColor = value;
        }

        public int BrushSize
        {
            get => _brushSize;
            set => _brushSize = value;
        }

        public bool BrushModeEnabled
        {
            get => _brushModeEnabled;
            set => _brushModeEnabled = value;
        }

        public Size ImageDisplaySize => new Size((int)_imageDisplayWidth, (int)_imageDisplayHeight);

        #endregion

        #region Paint

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (_editingImage == null)
            {
                e.Graphics.Clear(BackColor);
                return;
            }

            // 배경 채우기
            e.Graphics.Clear(BackColor);

            // 이미지 영역 업데이트
            UpdateImageRect();

            // 이미지 그리기 (고품질)
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.DrawImage(_editingImage, _imageRect);

            // 크기 조정 핸들 그리기
            DrawResizeHandles(e.Graphics);
        }

        private void UpdateImageRect()
        {
            if (_editingImage == null || Width == 0 || Height == 0)
            {
                _imageRect = Rectangle.Empty;
                return;
            }

            // 이미지를 중앙 정렬
            float x = (Width - _imageDisplayWidth) / 2f;
            float y = (Height - _imageDisplayHeight) / 2f;

            // 음수 방지
            if (x < 0) x = 0;
            if (y < 0) y = 0;

            _imageRect = new Rectangle((int)x, (int)y, (int)_imageDisplayWidth, (int)_imageDisplayHeight);
        }

        private void DrawResizeHandles(Graphics g)
        {
            if (_imageRect.IsEmpty)
                return;

            var handles = GetResizeHandles();
            foreach (var handle in handles)
            {
                g.FillRectangle(Brushes.Blue, handle);
                g.DrawRectangle(Pens.White, handle);
            }
        }

        private Rectangle[] GetResizeHandles()
        {
            int x = _imageRect.X;
            int y = _imageRect.Y;
            int w = _imageRect.Width;
            int h = _imageRect.Height;
            int hs = HANDLE_SIZE;

            return new Rectangle[]
            {
                new Rectangle(x - hs/2, y - hs/2, hs, hs),                  // TopLeft
                new Rectangle(x + w/2 - hs/2, y - hs/2, hs, hs),            // Top
                new Rectangle(x + w - hs/2, y - hs/2, hs, hs),              // TopRight
                new Rectangle(x + w - hs/2, y + h/2 - hs/2, hs, hs),        // Right
                new Rectangle(x + w - hs/2, y + h - hs/2, hs, hs),          // BottomRight
                new Rectangle(x + w/2 - hs/2, y + h - hs/2, hs, hs),        // Bottom
                new Rectangle(x - hs/2, y + h - hs/2, hs, hs),              // BottomLeft
                new Rectangle(x - hs/2, y + h/2 - hs/2, hs, hs)             // Left
            };
        }

        #endregion

        #region Mouse Events

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (_editingImage == null || e.Button != MouseButtons.Left)
                return;

            // 크기 조정 핸들 확인
            _activeHandle = GetHandleAtPoint(e.Location);
            if (_activeHandle != ResizeHandle.None)
            {
                _isResizing = true;
                _resizeStartPoint = e.Location;
                _resizeStartWidth = _imageDisplayWidth;
                _resizeStartHeight = _imageDisplayHeight;
                return;
            }

            // 브러시 모드: 그리기
            if (_brushModeEnabled && _imageRect.Contains(e.Location))
            {
                _isDrawing = true;
                _lastDrawPoint = ImagePointFromScreen(e.Location);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (_editingImage == null)
                return;

            // 크기 조정 중
            if (_isResizing && _activeHandle != ResizeHandle.None)
            {
                ResizeImageDisplay(e.Location);
                return;
            }

            // 크기 조정 핸들 위에 마우스가 있으면 커서 변경
            var handle = GetHandleAtPoint(e.Location);
            if (handle != ResizeHandle.None)
            {
                Cursor = GetCursorForHandle(handle);
                return;
            }
            else
            {
                Cursor = Cursors.Default;
            }

            // 브러시 모드: 그리기
            if (_isDrawing && _lastDrawPoint != Point.Empty && _brushModeEnabled && _imageRect.Contains(e.Location))
            {
                Point currentImagePoint = ImagePointFromScreen(e.Location);
                _imageGraphics.DrawLine(new Pen(_drawColor, _brushSize), _lastDrawPoint, currentImagePoint);
                _lastDrawPoint = currentImagePoint;
                Invalidate();
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (_isResizing)
            {
                _isResizing = false;
                _activeHandle = ResizeHandle.None;
            }

            if (_isDrawing)
            {
                _isDrawing = false;
                _lastDrawPoint = Point.Empty;
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            UpdateImageRect();
            Invalidate();
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// 화면 좌표를 이미지 좌표로 변환
        /// </summary>
        private Point ImagePointFromScreen(Point screenPoint)
        {
            if (_imageRect.IsEmpty || _editingImage == null)
                return Point.Empty;

            // 화면 좌표를 이미지 비율로 변환
            float scaleX = (float)_editingImage.Width / _imageRect.Width;
            float scaleY = (float)_editingImage.Height / _imageRect.Height;

            int imageX = (int)((screenPoint.X - _imageRect.X) * scaleX);
            int imageY = (int)((screenPoint.Y - _imageRect.Y) * scaleY);

            return new Point(imageX, imageY);
        }

        private ResizeHandle GetHandleAtPoint(Point pt)
        {
            var handles = GetResizeHandles();
            var handleTypes = new[]
            {
                ResizeHandle.TopLeft, ResizeHandle.Top, ResizeHandle.TopRight,
                ResizeHandle.Right, ResizeHandle.BottomRight, ResizeHandle.Bottom,
                ResizeHandle.BottomLeft, ResizeHandle.Left
            };

            for (int i = 0; i < handles.Length; i++)
            {
                if (handles[i].Contains(pt))
                    return handleTypes[i];
            }

            return ResizeHandle.None;
        }

        private Cursor GetCursorForHandle(ResizeHandle handle)
        {
            switch (handle)
            {
                case ResizeHandle.TopLeft:
                case ResizeHandle.BottomRight:
                    return Cursors.SizeNWSE;
                case ResizeHandle.TopRight:
                case ResizeHandle.BottomLeft:
                    return Cursors.SizeNESW;
                case ResizeHandle.Top:
                case ResizeHandle.Bottom:
                    return Cursors.SizeNS;
                case ResizeHandle.Left:
                case ResizeHandle.Right:
                    return Cursors.SizeWE;
                default:
                    return Cursors.Default;
            }
        }

        private void ResizeImageDisplay(Point currentPoint)
        {
            int deltaX = currentPoint.X - _resizeStartPoint.X;
            int deltaY = currentPoint.Y - _resizeStartPoint.Y;

            float newWidth = _resizeStartWidth;
            float newHeight = _resizeStartHeight;

            switch (_activeHandle)
            {
                case ResizeHandle.TopLeft:
                    newWidth -= deltaX;
                    newHeight -= deltaY;
                    break;
                case ResizeHandle.Top:
                    newHeight -= deltaY;
                    break;
                case ResizeHandle.TopRight:
                    newWidth += deltaX;
                    newHeight -= deltaY;
                    break;
                case ResizeHandle.Right:
                    newWidth += deltaX;
                    break;
                case ResizeHandle.BottomRight:
                    newWidth += deltaX;
                    newHeight += deltaY;
                    break;
                case ResizeHandle.Bottom:
                    newHeight += deltaY;
                    break;
                case ResizeHandle.BottomLeft:
                    newWidth -= deltaX;
                    newHeight += deltaY;
                    break;
                case ResizeHandle.Left:
                    newWidth -= deltaX;
                    break;
            }

            // 최소 크기 제한
            if (newWidth < 50) newWidth = 50;
            if (newHeight < 50) newHeight = 50;

            _imageDisplayWidth = newWidth;
            _imageDisplayHeight = newHeight;

            UpdateImageRect();
            Invalidate();
        }

        /// <summary>
        /// 표시 크기로 실제 이미지 리사이즈
        /// </summary>
        public Bitmap GetResizedImage()
        {
            if (_editingImage == null)
                return null;

            int targetWidth = (int)_imageDisplayWidth;
            int targetHeight = (int)_imageDisplayHeight;

            // 크기가 같으면 원본 반환
            if (targetWidth == _editingImage.Width && targetHeight == _editingImage.Height)
                return new Bitmap(_editingImage);

            // 리사이즈
            var resized = new Bitmap(targetWidth, targetHeight);
            using (var g = Graphics.FromImage(resized))
            {
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.DrawImage(_editingImage, 0, 0, targetWidth, targetHeight);
            }

            return resized;
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _imageGraphics?.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
