using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using AGVNavigationCore.Models;
using AGVNavigationCore.Controls;

namespace AGVMapEditor.Models
{
    /// <summary>
    /// 노드 타입에 따른 PropertyWrapper 팩토리
    /// </summary>
    public static class NodePropertyWrapperFactory
    {
        public static object CreateWrapper(MapNode node, List<MapNode> mapNodes)
        {
            switch (node.Type)
            {
                case NodeType.Label:
                    return new LabelNodePropertyWrapper(node, mapNodes);
                case NodeType.Image:
                    return new ImageNodePropertyWrapper(node, mapNodes);
                default:
                    return new NodePropertyWrapper(node, mapNodes);
            }
        }
    }

    /// <summary>
    /// 라벨 노드 전용 PropertyWrapper
    /// </summary>
    public class LabelNodePropertyWrapper
    {
        private MapNode _node;
        private List<MapNode> _mapNodes;

        public LabelNodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
        {
            _node = node;
            _mapNodes = mapNodes;
        }

        /// <summary>
        /// 래핑된 MapNode 인스턴스 접근
        /// </summary>
        public MapNode WrappedNode => _node;

        [Category("기본 정보")]
        [DisplayName("노드 ID")]
        [Description("노드의 고유 식별자")]
        [ReadOnly(true)]
        public string NodeId
        {
            get => _node.NodeId;
        }

        [Category("기본 정보")]
        [DisplayName("노드 타입")]
        [Description("노드의 타입")]
        [ReadOnly(true)]
        public NodeType Type
        {
            get => _node.Type;
        }

        [Category("라벨")]
        [DisplayName("텍스트")]
        [Description("표시할 텍스트")]
        public string LabelText
        {
            get => _node.LabelText;
            set
            {
                _node.LabelText = value ?? "";
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("폰트 패밀리")]
        [Description("폰트 패밀리")]
        public string FontFamily
        {
            get => _node.FontFamily;
            set
            {
                _node.FontFamily = value ?? "Arial";
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("폰트 크기")]
        [Description("폰트 크기")]
        public float FontSize
        {
            get => _node.FontSize;
            set
            {
                _node.FontSize = Math.Max(6, Math.Min(72, value));
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("폰트 스타일")]
        [Description("폰트 스타일")]
        public FontStyle FontStyle
        {
            get => _node.FontStyle;
            set
            {
                _node.FontStyle = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("전경색")]
        [Description("텍스트 색상")]
        public Color ForeColor
        {
            get => _node.ForeColor;
            set
            {
                _node.ForeColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("배경색")]
        [Description("배경 색상")]
        public Color BackColor
        {
            get => _node.BackColor;
            set
            {
                _node.BackColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("배경 표시")]
        [Description("배경을 표시할지 여부")]
        public bool ShowBackground
        {
            get => _node.ShowBackground;
            set
            {
                _node.ShowBackground = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("라벨")]
        [DisplayName("패딩")]
        [Description("텍스트 주변 여백 (픽셀 단위)")]
        public int Padding
        {
            get => _node.Padding;
            set
            {
                _node.Padding = Math.Max(0, Math.Min(50, value));
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("위치")]
        [DisplayName("X 좌표")]
        [Description("맵에서의 X 좌표")]
        public int PositionX
        {
            get => _node.Position.X;
            set
            {
                _node.Position = new Point(value, _node.Position.Y);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("위치")]
        [DisplayName("Y 좌표")]
        [Description("맵에서의 Y 좌표")]
        public int PositionY
        {
            get => _node.Position.Y;
            set
            {
                _node.Position = new Point(_node.Position.X, value);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("정보")]
        [DisplayName("생성 일시")]
        [Description("노드가 생성된 일시")]
        [ReadOnly(true)]
        public DateTime CreatedDate
        {
            get => _node.CreatedDate;
        }

        [Category("정보")]
        [DisplayName("수정 일시")]
        [Description("노드가 마지막으로 수정된 일시")]
        [ReadOnly(true)]
        public DateTime ModifiedDate
        {
            get => _node.ModifiedDate;
        }
    }

    /// <summary>
    /// 이미지 노드 전용 PropertyWrapper
    /// </summary>
    public class ImageNodePropertyWrapper
    {
        private MapNode _node;
        private List<MapNode> _mapNodes;

        public ImageNodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
        {
            _node = node;
            _mapNodes = mapNodes;
        }

        /// <summary>
        /// 래핑된 MapNode 인스턴스 접근
        /// </summary>
        public MapNode WrappedNode => _node;

        [Category("기본 정보")]
        [DisplayName("노드 ID")]
        [Description("노드의 고유 식별자")]
        [ReadOnly(true)]
        public string NodeId
        {
            get => _node.NodeId;
        }

        [Category("기본 정보")]
        [DisplayName("노드 타입")]
        [Description("노드의 타입")]
        [ReadOnly(true)]
        public NodeType Type
        {
            get => _node.Type;
        }

        [Category("이미지")]
        [DisplayName("이미지 경로")]
        [Description("이미지 파일 경로 (... 버튼으로 파일 선택)")]
        [Editor(typeof(ImagePathEditor), typeof(UITypeEditor))]
        public string ImagePath
        {
            get => _node.ImagePath;
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    _node.ImagePath = "";
                    return;
                }

                // 파일이 존재하면 Base64로 변환하여 저장
                if (System.IO.File.Exists(value))
                {
                    _node.ConvertImageToBase64(value);
                    _node.LoadImage(); // 이미지 다시 로드
                }
                else
                {
                    _node.ImagePath = value;
                }

                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("이미지")]
        [DisplayName("가로 배율")]
        [Description("가로 배율 (1.0 = 원본 크기)")]
        public float ScaleWidth
        {
            get => _node.Scale.Width;
            set
            {
                _node.Scale = new SizeF(Math.Max(0.1f, Math.Min(5.0f, value)), _node.Scale.Height);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("이미지")]
        [DisplayName("세로 배율")]
        [Description("세로 배율 (1.0 = 원본 크기)")]
        public float ScaleHeight
        {
            get => _node.Scale.Height;
            set
            {
                _node.Scale = new SizeF(_node.Scale.Width, Math.Max(0.1f, Math.Min(5.0f, value)));
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("이미지")]
        [DisplayName("투명도")]
        [Description("투명도 (0.0 = 투명, 1.0 = 불투명)")]
        public float Opacity
        {
            get => _node.Opacity;
            set
            {
                _node.Opacity = Math.Max(0.0f, Math.Min(1.0f, value));
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("이미지")]
        [DisplayName("회전각도")]
        [Description("회전 각도 (도 단위)")]
        public float Rotation
        {
            get => _node.Rotation;
            set
            {
                _node.Rotation = value % 360;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("위치")]
        [DisplayName("X 좌표")]
        [Description("맵에서의 X 좌표")]
        public int PositionX
        {
            get => _node.Position.X;
            set
            {
                _node.Position = new Point(value, _node.Position.Y);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("위치")]
        [DisplayName("Y 좌표")]
        [Description("맵에서의 Y 좌표")]
        public int PositionY
        {
            get => _node.Position.Y;
            set
            {
                _node.Position = new Point(_node.Position.X, value);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("정보")]
        [DisplayName("생성 일시")]
        [Description("노드가 생성된 일시")]
        [ReadOnly(true)]
        public DateTime CreatedDate
        {
            get => _node.CreatedDate;
        }

        [Category("정보")]
        [DisplayName("수정 일시")]
        [Description("노드가 마지막으로 수정된 일시")]
        [ReadOnly(true)]
        public DateTime ModifiedDate
        {
            get => _node.ModifiedDate;
        }
    }
    /// <summary>
    /// PropertyGrid에서 사용할 노드 속성 래퍼 클래스
    /// </summary>
    public class NodePropertyWrapper
    {
        private MapNode _node;
        private List<MapNode> _mapNodes;

        public NodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
        {
            _node = node;
            _mapNodes = mapNodes;
        }

        /// <summary>
        /// 래핑된 MapNode 인스턴스 접근
        /// </summary>
        public MapNode WrappedNode => _node;

        [Category("기본 정보")]
        [DisplayName("노드 ID")]
        [Description("노드의 고유 식별자")]
        [ReadOnly(true)]
        public string NodeId
        {
            get => _node.NodeId;
            set => _node.NodeId = value;
        }

        [Category("기본 정보")]
        [DisplayName("노드 이름")]
        [Description("노드의 표시 이름")]
        public string Name
        {
            get => _node.Name;
            set
            {
                _node.Name = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }



        [Category("기본 정보")]
        [DisplayName("노드 타입")]
        [Description("노드의 타입 (Normal, Rotation, Docking, Charging)")]
        public NodeType Type
        {
            get => _node.Type;
            set
            {
                _node.Type = value;
                _node.CanRotate = value == NodeType.Rotation;
                _node.SetDefaultColorByType(value);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("기본 정보")]
        [DisplayName("도킹 방향")]
        [Description("도킹이 필요한 노드의 경우 AGV 진입 방향 (DontCare: 방향 무관, Forward: 전진 도킹, Backward: 후진 도킹)")]
        public DockingDirection DockDirection
        {
            get => _node.DockDirection;
            set
            {
                _node.DockDirection = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }


    


        [Category("위치")]
        [DisplayName("X 좌표")]
        [Description("맵에서의 X 좌표")]
        public int PositionX
        {
            get => _node.Position.X;
            set
            {
                _node.Position = new Point(value, _node.Position.Y);
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("위치")]
        [DisplayName("Y 좌표")]
        [Description("맵에서의 Y 좌표")]
        public int PositionY
        {
            get => _node.Position.Y;
            set
            {
                _node.Position = new Point(_node.Position.X, value);
                _node.ModifiedDate = DateTime.Now;
            }
        }



        [Category("고급")]
        [DisplayName("회전 가능")]
        [Description("이 노드에서 AGV가 회전할 수 있는지 여부")]
        public bool CanRotate
        {
            get => _node.CanRotate;
            set
            {
                _node.CanRotate = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("고급")]
        [DisplayName("RFID")]
        [Description("RFID ID")]
        public string RFID
        {
            get => _node.RfidId;
            set
            {
                _node.RfidId = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }




        [Category("고급")]
        [DisplayName("활성화")]
        [Description("노드 활성화 여부")]
        public bool IsActive
        {
            get => _node.IsActive;
            set
            {
                _node.IsActive = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("노드 배경색")]
        [Description("노드 배경 색상")]
        public Color DisplayColor
        {
            get => _node.DisplayColor;
            set
            {
                _node.DisplayColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("글자 색상")]
        [Description("노드 텍스트 색상 (NodeId, Name 등)")]
        public Color ForeColor
        {
            get => _node.ForeColor;
            set
            {
                _node.ForeColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("글자 크기")]
        [Description("노드 텍스트 크기 (픽셀)")]
        public float TextFontSize
        {
            get => _node.TextFontSize;
            set
            {
                _node.TextFontSize = Math.Max(5.0f, Math.Min(20.0f, value));
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("글자 굵게")]
        [Description("노드 텍스트 볼드 표시")]
        public bool TextFontBold
        {
            get => _node.TextFontBold;
            set
            {
                _node.TextFontBold = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("이름 말풍선 배경색")]
        [Description("노드 이름 말풍선(하단 표시) 배경색")]
        public Color NameBubbleBackColor
        {
            get => _node.NameBubbleBackColor;
            set
            {
                _node.NameBubbleBackColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("표시")]
        [DisplayName("이름 말풍선 글자색")]
        [Description("노드 이름 말풍선(하단 표시) 글자색")]
        public Color NameBubbleForeColor
        {
            get => _node.NameBubbleForeColor;
            set
            {
                _node.NameBubbleForeColor = value;
                _node.ModifiedDate = DateTime.Now;
            }
        }

        [Category("정보")]
        [DisplayName("생성 일시")]
        [Description("노드가 생성된 일시")]
        [ReadOnly(true)]
        public DateTime CreatedDate
        {
            get => _node.CreatedDate;
        }

        [Category("정보")]
        [DisplayName("수정 일시")]
        [Description("노드가 마지막으로 수정된 일시")]
        [ReadOnly(true)]
        public DateTime ModifiedDate
        {
            get => _node.ModifiedDate;
        }
    }

    /// <summary>
    /// 다중 노드 선택 시 공통 속성 편집용 래퍼
    /// </summary>
    public class MultiNodePropertyWrapper
    {
        private List<MapNode> _nodes;

        public MultiNodePropertyWrapper(List<MapNode> nodes)
        {
            _nodes = nodes ?? new List<MapNode>();
        }

        [Category("다중 선택")]
        [DisplayName("선택된 노드 수")]
        [Description("현재 선택된 노드의 개수")]
        [ReadOnly(true)]
        public int SelectedCount => _nodes.Count;

        [Category("표시")]
        [DisplayName("노드 배경색")]
        [Description("선택된 모든 노드의 배경색을 일괄 변경")]
        public Color DisplayColor
        {
            get => _nodes.Count > 0 ? _nodes[0].DisplayColor : Color.Blue;
            set
            {
                foreach (var node in _nodes)
                {
                    node.DisplayColor = value;
                    node.ModifiedDate = DateTime.Now;
                }
            }
        }

        [Category("표시")]
        [DisplayName("글자 색상")]
        [Description("선택된 모든 노드의 글자 색상을 일괄 변경")]
        public Color ForeColor
        {
            get => _nodes.Count > 0 ? _nodes[0].ForeColor : Color.Black;
            set
            {
                foreach (var node in _nodes)
                {
                    node.ForeColor = value;
                    node.ModifiedDate = DateTime.Now;
                }
            }
        }

        [Category("표시")]
        [DisplayName("글자 크기")]
        [Description("선택된 모든 노드의 글자 크기를 일괄 변경 (5~20 픽셀)")]
        public float TextFontSize
        {
            get => _nodes.Count > 0 ? _nodes[0].TextFontSize : 7.0f;
            set
            {
                var validValue = Math.Max(5.0f, Math.Min(20.0f, value));
                System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontSize 변경 시작: {validValue}, 노드 수: {_nodes.Count}");

                foreach (var node in _nodes)
                {
                    System.Diagnostics.Debug.WriteLine($"  - 노드 {node.NodeId}: {node.TextFontSize} → {validValue}");
                    node.TextFontSize = validValue;
                    node.ModifiedDate = DateTime.Now;
                    System.Diagnostics.Debug.WriteLine($"  - 변경 후: {node.TextFontSize}");
                }

                System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontSize 변경 완료");
            }
        }

        [Category("표시")]
        [DisplayName("글자 굵게")]
        [Description("선택된 모든 노드의 글자 굵기를 일괄 변경")]
        public bool TextFontBold
        {
            get
            {
                var result = _nodes.Count > 0 ? _nodes[0].TextFontBold : true;
                System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold GET: {result}");
                return result;
            }
            set
            {
                System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold 변경 시작: {value}, 노드 수: {_nodes.Count}");

                foreach (var node in _nodes)
                {
                    System.Diagnostics.Debug.WriteLine($"  - 노드 {node.NodeId}: {node.TextFontBold} → {value}");
                    node.TextFontBold = value;
                    node.ModifiedDate = DateTime.Now;
                    System.Diagnostics.Debug.WriteLine($"  - 변경 후: {node.TextFontBold}");
                }

                System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold 변경 완료");
            }
        }

        [Category("표시")]
        [DisplayName("이름 말풍선 배경색")]
        [Description("선택된 모든 노드의 이름 말풍선(하단 표시) 배경색을 일괄 변경")]
        public Color NameBubbleBackColor
        {
            get => _nodes.Count > 0 ? _nodes[0].NameBubbleBackColor : Color.Gold;
            set
            {
                foreach (var node in _nodes)
                {
                    node.NameBubbleBackColor = value;
                    node.ModifiedDate = DateTime.Now;
                }
            }
        }

        [Category("표시")]
        [DisplayName("이름 말풍선 글자색")]
        [Description("선택된 모든 노드의 이름 말풍선(하단 표시) 글자색을 일괄 변경")]
        public Color NameBubbleForeColor
        {
            get => _nodes.Count > 0 ? _nodes[0].NameBubbleForeColor : Color.Black;
            set
            {
                foreach (var node in _nodes)
                {
                    node.NameBubbleForeColor = value;
                    node.ModifiedDate = DateTime.Now;
                }
            }
        }

        [Category("고급")]
        [DisplayName("활성화")]
        [Description("선택된 모든 노드의 활성화 상태를 일괄 변경")]
        public bool IsActive
        {
            get => _nodes.Count > 0 ? _nodes[0].IsActive : true;
            set
            {
                foreach (var node in _nodes)
                {
                    node.IsActive = value;
                    node.ModifiedDate = DateTime.Now;
                }
            }
        }

        [Category("정보")]
        [DisplayName("안내")]
        [Description("다중 선택 시 공통 속성만 변경할 수 있습니다")]
        [ReadOnly(true)]
        public string HelpText => "위 속성을 변경하면 선택된 모든 노드에 일괄 적용됩니다.";
    }

    /// <summary>
    /// 캔버스 속성 래퍼 (배경색 등 캔버스 전체 속성 편집)
    /// </summary>
    public class CanvasPropertyWrapper
    {
        private UnifiedAGVCanvas _canvas;

        public CanvasPropertyWrapper(UnifiedAGVCanvas canvas)
        {
            _canvas = canvas;
        }

        [Category("배경")]
        [DisplayName("배경색")]
        [Description("맵 캔버스 배경색")]
        public Color BackgroundColor
        {
            get => _canvas.BackColor;
            set
            {
                _canvas.BackColor = value;
                _canvas.Invalidate();
            }
        }

        [Category("그리드")]
        [DisplayName("그리드 표시")]
        [Description("그리드 표시 여부")]
        public bool ShowGrid
        {
            get => _canvas.ShowGrid;
            set
            {
                _canvas.ShowGrid = value;
                _canvas.Invalidate();
            }
        }

        [Category("정보")]
        [DisplayName("설명")]
        [Description("맵 캔버스 전체 속성")]
        [ReadOnly(true)]
        public string Description
        {
            get => "빈 공간을 클릭하면 캔버스 전체 속성을 편집할 수 있습니다.";
        }
    }

}