using AGVNavigationCore.Models;
using AGVNavigationCore.PathFinding;
using AGVNavigationCore.PathFinding.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Reflection.Emit;
using System.Windows.Forms;

namespace AGVNavigationCore.Controls
{
    /// <summary>
    /// 통합 AGV 캔버스 컨트롤
    /// 맵 편집, AGV 시뮬레이션, 실시간 모니터링을 모두 지원
    /// </summary>
    public partial class UnifiedAGVCanvas : UserControl
    {
        #region Constants

        private const int NODE_SIZE = 18;
        private const int NODE_RADIUS = NODE_SIZE / 2;
        private const int GRID_SIZE = 20;
        private const float CONNECTION_WIDTH = 1.0f;
        private const int SNAP_DISTANCE = 10;
        private const int AGV_SIZE = 40;
        private const int CONNECTION_ARROW_SIZE = 8;

        #endregion

        #region Enums

        /// <summary>
        /// 캔버스 모드
        /// </summary>
        public enum CanvasMode
        {
            Edit,       // 편집 가능 (맵 에디터)
            Sync,       // 동기화 모드 (장비 설정 동기화)
            Emulator,   // 에뮬레이터 모드
            Run         // 가동 모드 (User Request)
        }

        /// <summary>
        /// 편집 모드 (CanvasMode.Edit일 때만 적용)
        /// </summary>
        public enum EditMode
        {
            Select,         // 선택 모드
            Move,           // 이동 모드
            AddNode,        // 노드 추가 모드
            Connect,        // 연결 모드
            Delete,         // 삭제 모드
            DeleteConnection, // 연결 삭제 모드
            AddLabel,       // 라벨 추가 모드
            AddImage,       // 이미지 추가 모드
            ConnectDirection, // 방향 연결 모드
        }

        #endregion

        #region Fields

        // 캔버스 모드
        private CanvasMode _canvasMode = CanvasMode.Edit;
        private EditMode _editMode = EditMode.Select;

        // 맵 데이터
        private List<MapNode> _nodes;
        private List<MapLabel> _labels;     // 추가
        private List<MapImage> _images;     // 추가
        private List<MapMark> _marks;
        private List<MapMagnet> _magnets;

        // 선택된 객체들 (나중에 NodeBase로 통일 필요)
        private NodeBase _selectedNode;

        private List<NodeBase> _selectedNodes; // 다중 선택 (NodeBase로 변경 고려)

        private NodeBase _hoveredNode;

        private NodeBase _destinationNode;

        // AGV 관련
        private List<IAGV> _agvList;
        private Dictionary<string, Point> _agvPositions;
        private Dictionary<string, AgvDirection> _agvDirections;
        private Dictionary<string, AGVState> _agvStates;

        // 경로 관련
        private AGVPathResult _currentPath;
        private List<AGVPathResult> _allPaths;

        // 도킹 검증 관련
        private Dictionary<string, bool> _dockingErrors;

        // UI 요소들
        private Image _companyLogo;
        private string _companyLogoPath = string.Empty;
        private string _measurementInfo = string.Empty;

        // 편집 관련 (EditMode에서만 사용)
        private bool _isDragging;
        private Point _dragOffset;
        private Point _dragStartPosition; // 드래그 시작 위치 (고스트 표시용)
        private Point _lastMousePosition;
        private bool _isConnectionMode;
        private MapNode _connectionStartNode;
        private Point _connectionEndPoint;
        private int _mouseMoveCounter = 0; // 디버그용: MouseMove 실행 횟수
        private int _dragHandleIndex = -1; // 드래그 중인 핸들 인덱스
        private const int HANDLE_SIZE = 8; // 편집 핸들 크기

        // 영역 선택 관련
        private bool _isAreaSelecting;
        private Point _areaSelectStart;
        private Point _areaSelectEnd;

        // 그리드 및 줌 관련
        private bool _showGrid = true;
        private float _zoomFactor = 1.0f;
        private PointF _panOffset = PointF.Empty; // float 정밀도로 변경 (팬 이동 정확도 개선)
        private bool _isPanning;

        // 자동 증가 카운터
        private int _nodeCounter = 1;

        // 강조 연결
        private (string FromNodeId, string ToNodeId)? _highlightedConnection = null;

        // RFID 중복 검사
        private HashSet<string> _duplicateRfidNodes = new HashSet<string>();

        // 동기화 모드 관련
        private string _syncMessage = "동기화 중...";
        private float _syncProgress = 0.0f;
        private string _syncDetail = "";

        string _systemmesage = "";
        string _infomessage = "";
        string _tagignoreMessage = "";
        bool showalertsystem = false;
        bool showinfo = false;
        bool showtagigreno = false;
        DateTime tagignoretime = DateTime.Now;
        public void SetTagIgnore(string m)
        {
            _tagignoreMessage = m;
            tagignoretime = DateTime.Now;
            showtagigreno = !string.IsNullOrEmpty(m);
        }
        public void SetInfoMessage(string m)
        {
            _infomessage = m;
            showinfo = !string.IsNullOrEmpty(m);
        }
        public void SetSystemMessage(string m)
        {
            _systemmesage = m;
            showalertsystem = !string.IsNullOrEmpty(m);
        }

        // 브러쉬 및 펜
        private Brush _normalNodeBrush;
        private Brush _rotationNodeBrush;
        private Brush _dockingNodeBrush;
        private Brush _chargingNodeBrush;
        private Brush _selectedNodeBrush;
        private Brush _hoveredNodeBrush;
        private Brush _destinationNodeBrush;
        private Brush _gridBrush;
        private Brush _agvBrush;
        private Brush _pathBrush;

        private Pen _connectionPen;
        private Pen _gridPen;
        private Pen _tempConnectionPen;
        private Pen _selectedNodePen;
        private Pen _destinationNodePen;
        private Pen _pathPen;
        private Pen _agvPen;
        private Pen _highlightedConnectionPen;
        private Pen _magnetPen;
        private Pen _markPen;
        private ToolTip _tooltip;

        // 컨텍스트 메뉴
        private ContextMenuStrip _contextMenu;

        // 이벤트
        public event EventHandler<NodeBase> NodeRightClicked;

        #endregion

        #region Events

        // 맵 편집 이벤트
        public delegate void NodeSelectHandler(object sender, NodeBase node, MouseEventArgs e);
        public event NodeSelectHandler NodeSelect;

        public event EventHandler<NodeBase> NodeAdded;
        public event EventHandler<List<NodeBase>> NodesSelected; // 다중 선택 이벤트
        public event EventHandler<NodeBase> NodeDeleted;
        public event EventHandler<NodeBase> NodeMoved;
        public event EventHandler<(MapNode From, MapNode To)> ConnectionCreated; // 연결 생성 이벤트 추가
        public event EventHandler<(MapNode From, MapNode To)> ConnectionDeleted;
        public event EventHandler<MapImage> ImageDoubleClicked;
        public event EventHandler<MapLabel> LabelDoubleClicked;
        public event EventHandler MapChanged;

        #endregion

        #region Properties

        public string PredictMessage { get; set; } = "";
        public string MapFileName { get; set; } = "";

        /// <summary>
        /// 캔버스 모드
        /// </summary>
        public CanvasMode Mode
        {
            get => _canvasMode;
            set
            {
                _canvasMode = value;
                UpdateModeUI();
                Invalidate();
            }
        }

        /// <summary>
        /// 강조해서 표시할 특정 노드 ID (예: Gateway)
        /// 이 값이 설정되면 해당 노드만 강조 표시됩니다.
        /// </summary>
        public string HighlightNodeId { get; set; }

        public void RemoveItem(NodeBase item)
        {
            if (item is MapImage img) RemoveImage(img);
            else if (item is MapLabel lb) RemoveLabel(lb);
            else if (item is MapNode nd) RemoveNode(nd);
            else if (item is MapMark mk) RemoveMark(mk);
            else if (item is MapMagnet mg) RemoveMagnet(mg);
            else throw new Exception("unknown type");

        }
        public void RemoveNode(MapNode node)
        {
            if (_nodes != null && _nodes.Contains(node))
            {
                // 🔥 삭제되는 노드와 연결된 다른 노드들의 연결 정보도 삭제
                foreach (var otherNode in _nodes.ToList()) // ToList()로 복사본 순회 (안전장치)
                {
                    if (otherNode == node) continue;

                    // 다른 노드 -> 삭제되는 노드 연결 제거
                    if (otherNode.ConnectedNodes.Contains(node.Id))
                    {
                        otherNode.RemoveConnection(node.Id);
                    }
                }

                _nodes.Remove(node);
                Invalidate();
            }
        }
        public void RemoveLabel(MapLabel label)
        {
            if (_labels != null && _labels.Contains(label))
            {
                _labels.Remove(label);
                Invalidate();
            }
        }

        public void RemoveImage(MapImage image)
        {
            if (_images != null && _images.Contains(image))
            {
                _images.Remove(image);
                Invalidate();
            }
        }

        public void RemoveMark(MapMark mark)
        {
            if (_marks != null && _marks.Contains(mark))
            {
                _marks.Remove(mark);
                Invalidate();
            }
        }

        public void RemoveMagnet(MapMagnet magnet)
        {
            if (_magnets != null && _magnets.Contains(magnet))
            {
                _magnets.Remove(magnet);
                Invalidate();
            }
        }

        /// <summary>
        /// 편집 모드 (CanvasMode.Edit일 때만 적용)
        /// </summary>
        public EditMode CurrentEditMode
        {
            get => _editMode;
            set
            {
                if (_canvasMode != CanvasMode.Edit) return;

                _editMode = value;
                if (_editMode != EditMode.Connect)
                {
                    CancelConnection();
                }
                Cursor = GetCursorForMode(_editMode);
                Invalidate();
            }
        }

        /// <summary>
        /// 외부에서 Pan(X,Y) 및 Zoom 값을 설정합니다.
        /// </summary>
        /// <param name="panX">Pan X 좌표</param>
        /// <param name="panY">Pan Y 좌표</param>
        /// <param name="zoom">Zoom Level (0.1 ~ 5.0)</param>
        public void SetView(float panX, float panY, float zoom)
        {
            // Zoom 값 범위 제한
            float newZoom = Math.Max(0.1f, Math.Min(5.0f, zoom));

            _panOffset = new PointF(panX, panY);
            _zoomFactor = newZoom;

            Invalidate();
        }

        [Browsable(false)]
        public PointF PanOffset
        {
            get => _panOffset;
            set
            {
                _panOffset = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 그리드 표시 여부
        /// </summary>
        public bool ShowGrid
        {
            get => _showGrid;
            set
            {
                _showGrid = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 줌 팩터
        /// </summary>
        public float ZoomFactor
        {
            get => _zoomFactor;
            set
            {
                _zoomFactor = Math.Max(0.1f, Math.Min(5.0f, value));
                Invalidate();
            }
        }

        [Browsable(false)]
        public MapImage SelectedImage
        {
            get { return this._selectedNode as MapImage; }
        }

        [Browsable(false)]
        public MapLabel SelectedLabel
        {
            get { return this._selectedNode as MapLabel; }
        }

        [Browsable(false)]
        public MapMark SelectedMark
        {
            get { return this._selectedNode as MapMark; }
        }


        [Browsable(false)]
        public MapMagnet SelectedMagnet
        {
            get { return this._selectedNode as MapMagnet; }
        }

        /// <summary>
        /// 선택된 노드 (단일)
        /// </summary>
        public NodeBase SelectedNode
        {
            get { return this._selectedNode; }
            set
            {
                _selectedNode = value;
                if (value != null)
                {
                    _selectedNodes.Clear();
                    _selectedNodes.Add(value);
                }
                else
                {
                    _selectedNodes.Clear();
                }
                Invalidate();
            }
        }

        /// <summary>
        /// 선택된 노드들 (다중)
        /// </summary>
        public List<NodeBase> SelectedNodes => _selectedNodes ?? new List<NodeBase>();


        public List<NodeBase> Items
        {
            get
            {
                List<NodeBase> items = new List<NodeBase>();
                if (Nodes != null && Nodes.Any()) items.AddRange(Nodes);
                if (Labels != null && Labels.Any()) items.AddRange(Labels);
                if (Images != null && Images.Any()) items.AddRange(Images);
                if (Marks != null && Marks.Any()) items.AddRange(Marks);
                if (Magnets != null && Magnets.Any()) items.AddRange(Magnets);
                return items;
            }
        }

        /// <summary>
        /// Map file loading 결과를 셋팅합니다
        /// </summary>
        /// <param name="result"></param>
        public void SetMapLoadResult(MapLoader.MapLoadResult result)
        {
            this.Nodes = result.Nodes;
            this.Labels = result.Labels; // 추가
            this.Images = result.Images; // 추가
            this.Marks = result.Marks;
            this.Magnets = result.Magnets;

            // 🔥 맵 설정 적용 (배경색, 그리드 표시)
            if (result.Settings != null)
            {
                this.BackColor = Color.FromArgb(result.Settings.BackgroundColorArgb);
                this.ShowGrid = result.Settings.ShowGrid;
            }

            this.FitToNodes();
        }

        /// <summary>
        /// 맵 데이터를 셋팅합니다
        /// </summary>
        public void SetMapData(List<MapNode> nodes, List<MapLabel> labels = null, List<MapImage> images = null, List<MapMark> marks = null, List<MapMagnet> magnets = null)
        {
            this.Nodes = nodes;
            this.Labels = labels ?? new List<MapLabel>();
            this.Images = images ?? new List<MapImage>();
            this.Marks = marks ?? new List<MapMark>();
            this.Magnets = magnets ?? new List<MapMagnet>();
            this.FitToNodes();
        }

        /// <summary>
        /// 노드 목록
        /// </summary>
        public List<MapNode> Nodes
        {
            get => _nodes ?? new List<MapNode>();
            set
            {
                _nodes = value ?? new List<MapNode>();

                // 기존 노드들의 최대 번호를 찾아서 _nodeCounter 설정
                UpdateNodeCounter();

                // RFID 중복값 검사
                DetectDuplicateRfidNodes();

                Invalidate();
            }
        }

        /// <summary>
        /// 라벨 목록
        /// </summary>
        public List<MapLabel> Labels
        {
            get => _labels ?? new List<MapLabel>();
            set
            {
                _labels = value ?? new List<MapLabel>();
                Invalidate();
            }
        }

        /// <summary>
        /// 이미지 목록
        /// </summary>
        public List<MapImage> Images
        {
            get => _images ?? new List<MapImage>();
            set
            {
                _images = value ?? new List<MapImage>();
                Invalidate();
            }
        }

        /// <summary>
        /// 마크 목록
        /// </summary>
        public List<MapMark> Marks
        {
            get => _marks ?? new List<MapMark>();
            set
            {
                _marks = value ?? new List<MapMark>();
                Invalidate();
            }
        }

        /// <summary>
        /// 마그넷 목록
        /// </summary>
        public List<MapMagnet> Magnets
        {
            get => _magnets ?? new List<MapMagnet>();
            set
            {
                _magnets = value ?? new List<MapMagnet>();
                Invalidate();
            }
        }

        /// <summary>
        /// AGV 목록
        /// </summary>
        public List<IAGV> AGVList
        {
            get => _agvList ?? new List<IAGV>();
            set
            {
                _agvList = value ?? new List<IAGV>();
                UpdateAGVData();
                Invalidate();
            }
        }

        /// <summary>
        /// 현재 표시할 경로
        /// </summary>
        public AGVPathResult CurrentPath
        {
            get => _currentPath;
            set
            {
                _currentPath = value;
                UpdateDestinationNode();
                Invalidate();
            }
        }

        /// <summary>
        /// 상세경로가 설정되어있는가?
        /// </summary>
        /// <returns></returns>
        public bool HasPath()
        {
            if (_currentPath == null) return false;
            if (_currentPath.DetailedPath == null) return false;
            return _currentPath.DetailedPath.Any();
        }

        /// <summary>
        /// 모든 경로 목록 (다중 AGV 경로 표시용)
        /// </summary>
        public List<AGVPathResult> AllPaths
        {
            get => _allPaths ?? new List<AGVPathResult>();
            set
            {
                _allPaths = value ?? new List<AGVPathResult>();
                Invalidate();
            }
        }

        /// <summary>
        /// 회사 로고 이미지
        /// </summary>
        public Image CompanyLogo
        {
            get => _companyLogo;
            set
            {
                _companyLogo = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 측정 정보 텍스트
        /// </summary>
        public string MeasurementInfo
        {
            get => _measurementInfo;
            set
            {
                _measurementInfo = value;
                Invalidate();
            }
        }

        #endregion

        #region Connection Highlighting

        /// <summary>
        /// 특정 연결을 강조 표시
        /// </summary>
        /// <param name="fromNodeId">시작 노드 ID</param>
        /// <param name="toNodeId">끝 노드 ID</param>
        public void HighlightConnection(string fromNodeId, string toNodeId)
        {
            if (string.IsNullOrEmpty(fromNodeId) || string.IsNullOrEmpty(toNodeId))
            {
                _highlightedConnection = null;
            }
            else
            {
                // 사전순으로 정렬하여 저장 (연결이 단일 방향으로 저장되므로)
                if (string.Compare(fromNodeId, toNodeId, StringComparison.Ordinal) <= 0)
                {
                    _highlightedConnection = (fromNodeId, toNodeId);
                }
                else
                {
                    _highlightedConnection = (toNodeId, fromNodeId);
                }
            }

            Invalidate();
        }

        /// <summary>
        /// 연결 강조 표시 해제
        /// </summary>
        public void ClearHighlightedConnection()
        {
            _highlightedConnection = null;
            Invalidate();
        }

        #endregion

        #region Constructor

        public UnifiedAGVCanvas()
        {
            InitializeComponent();
            InitializeCanvas();
        }

        #endregion

        #region Initialization

        private void InitializeCanvas()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                     ControlStyles.UserPaint |
                     ControlStyles.DoubleBuffer |
                     ControlStyles.ResizeRedraw, true);

            _nodes = new List<MapNode>();
            _labels = new List<MapLabel>();
            _images = new List<MapImage>();
            _marks = new List<MapMark>();
            _magnets = new List<MapMagnet>();

            _selectedNodes = new List<NodeBase>(); // 다중 선택 리스트 초기화
            _agvList = new List<IAGV>();
            _agvPositions = new Dictionary<string, Point>();
            _agvDirections = new Dictionary<string, AgvDirection>();
            _agvStates = new Dictionary<string, AGVState>();
            _allPaths = new List<AGVPathResult>();
            _dockingErrors = new Dictionary<string, bool>();

            InitializeBrushesAndPens();
            CreateContextMenu();

            _tooltip = new ToolTip();
            _tooltip.AutoPopDelay = 5000;
            _tooltip.InitialDelay = 1000;
            _tooltip.ReshowDelay = 500;
            _tooltip.ShowAlways = true;
        }

        private void InitializeBrushesAndPens()
        {
            // 노드 브러쉬
            _normalNodeBrush = new SolidBrush(Color.LightBlue);
            _rotationNodeBrush = new SolidBrush(Color.Yellow);
            _dockingNodeBrush = new SolidBrush(Color.Orange);
            _chargingNodeBrush = new SolidBrush(Color.Green);
            _selectedNodeBrush = new SolidBrush(Color.Red);
            _hoveredNodeBrush = new SolidBrush(Color.LightCyan);
            _destinationNodeBrush = new SolidBrush(Color.Gold);

            // AGV 및 경로 브러쉬
            _agvBrush = new SolidBrush(Color.Red);
            _pathBrush = new SolidBrush(Color.Purple);

            // 그리드 브러쉬
            _gridBrush = new SolidBrush(Color.LightGray);

            // 펜
            _connectionPen = new Pen(Color.White, CONNECTION_WIDTH);
            _connectionPen.DashStyle = DashStyle.Dash;
            _connectionPen.EndCap = LineCap.ArrowAnchor;

            _gridPen = new Pen(Color.LightGray, 1);
            _tempConnectionPen = new Pen(Color.Orange, 2) { DashStyle = DashStyle.Dash };
            _selectedNodePen = new Pen(Color.Red, 3);
            _destinationNodePen = new Pen(Color.Orange, 4);
            _pathPen = new Pen(Color.Purple, 3);
            _agvPen = new Pen(Color.Red, 3);
            _highlightedConnectionPen = new Pen(Color.Red, 6) { DashStyle = DashStyle.Solid };
            _magnetPen = new Pen(Color.FromArgb(100, Color.LightSkyBlue), 15) { DashStyle = DashStyle.Solid, StartCap = LineCap.Round, EndCap = LineCap.Round };
            _markPen = new Pen(Color.White, 3); // 마크는 흰색 선으로 표시
        }

        private void CreateContextMenu()
        {
            _contextMenu = new ContextMenuStrip();
            // 컨텍스트 메뉴는 EditMode에서만 사용
        }

        private void UpdateModeUI()
        {
            // 모드에 따른 UI 업데이트
            _contextMenu.Enabled = true;
            Cursor = GetCursorForMode(_editMode);
        }

        #endregion

        #region AGV Management

        /// <summary>
        /// AGV 위치 업데이트
        /// </summary>
        public void UpdateAGVPosition(string agvId, Point position)
        {
            if (_agvPositions.ContainsKey(agvId))
                _agvPositions[agvId] = position;
            else
                _agvPositions.Add(agvId, position);

            Invalidate();
        }

        /// <summary>
        /// AGV 방향 업데이트
        /// </summary>
        public void UpdateAGVDirection(string agvId, AgvDirection direction)
        {
            if (_agvDirections.ContainsKey(agvId))
                _agvDirections[agvId] = direction;
            else
                _agvDirections.Add(agvId, direction);

            Invalidate();
        }

        /// <summary>
        /// AGV 상태 업데이트
        /// </summary>
        public void UpdateAGVState(string agvId, AGVState state)
        {
            if (_agvStates.ContainsKey(agvId))
                _agvStates[agvId] = state;
            else
                _agvStates.Add(agvId, state);

            Invalidate();
        }

        /// <summary>
        /// AGV 위치 설정 (시뮬레이터용)
        /// </summary>
        /// <param name="agvId">AGV ID</param>
        /// <param name="position">새로운 위치</param>
        public void SetAGVPosition(string agvId, MapNode node, AgvDirection direction)
        {
            UpdateAGVPosition(agvId, node.Position);
            UpdateAGVDirection(agvId, direction);
        }

        /// <summary>
        /// AGV 데이터 동기화
        /// </summary>
        private void UpdateAGVData()
        {
            if (_agvList == null) return;

            foreach (var agv in _agvList)
            {
                UpdateAGVPosition(agv.AgvId, agv.CurrentPosition);
                UpdateAGVDirection(agv.AgvId, agv.CurrentDirection);
                UpdateAGVState(agv.AgvId, agv.CurrentState);
            }
        }

        #endregion

        #region Helper Methods

        private Cursor GetCursorForMode(EditMode mode)
        {
            if (_canvasMode != CanvasMode.Edit)
                return Cursors.Default;

            switch (mode)
            {
                case EditMode.AddNode:
                    return Cursors.Cross;
                case EditMode.Move:
                    return Cursors.SizeAll;
                case EditMode.Connect:
                    return Cursors.Hand;
                case EditMode.Delete:
                    return Cursors.No;
                default:
                    return Cursors.Default;
            }
        }

        private void CancelConnection()
        {
            _isConnectionMode = false;
            _connectionStartNode = null;
            _connectionEndPoint = Point.Empty;
            Invalidate();
        }

        private void UpdateDestinationNode()
        {
            _destinationNode = null;

            if (_currentPath != null && _currentPath.Success && _currentPath.Path != null && _currentPath.Path.Count > 0)
            {
                // 경로의 마지막 노드가 목적지
                _destinationNode = _currentPath.Path[_currentPath.Path.Count - 1];
            }
        }

        /// <summary>
        /// 동기화 상태 설정
        /// </summary>
        /// <param name="message">메인 메시지</param>
        /// <param name="progress">진행률 (0.0 ~ 1.0)</param>
        /// <param name="detail">상세 메시지</param>
        public void SetSyncStatus(string message, float progress, string detail = "")
        {
            _syncMessage = message;
            _syncProgress = Math.Max(0.0f, Math.Min(1.0f, progress));
            _syncDetail = detail;

            if (_canvasMode != CanvasMode.Sync)
            {
                _canvasMode = CanvasMode.Sync;
                UpdateModeUI();
            }

            Invalidate();
        }

        /// <summary>
        /// 동기화 모드 종료
        /// </summary>
        public void ExitSyncMode(CanvasMode newmode)
        {
            if (_canvasMode == CanvasMode.Sync)
            {
                _canvasMode = newmode; // 기본 모드로 복귀 (또는 이전 모드)
                UpdateModeUI();
                Invalidate();
            }
        }

        #endregion

        #region Cleanup

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {

                // 브러쉬 정리
                _normalNodeBrush?.Dispose();
                _rotationNodeBrush?.Dispose();
                _dockingNodeBrush?.Dispose();
                _chargingNodeBrush?.Dispose();
                _selectedNodeBrush?.Dispose();
                _hoveredNodeBrush?.Dispose();
                _destinationNodeBrush?.Dispose();
                _gridBrush?.Dispose();
                _agvBrush?.Dispose();
                _pathBrush?.Dispose();

                // 펜 정리
                _connectionPen?.Dispose();
                _gridPen?.Dispose();
                _tempConnectionPen?.Dispose();
                _selectedNodePen?.Dispose();
                _destinationNodePen?.Dispose();
                _pathPen?.Dispose();
                _agvPen?.Dispose();
                _highlightedConnectionPen?.Dispose();
                _magnetPen?.Dispose();
                _markPen?.Dispose();

                // 컨텍스트 메뉴 정리
                _contextMenu?.Dispose();

                // 이미지 정리
                _companyLogo?.Dispose();

            }

            base.Dispose(disposing);
        }

        #endregion

        /// <summary>
        /// RFID 중복값을 가진 노드들을 감지하고 표시
        /// 나중에 추가된 노드(인덱스가 더 큰)를 중복으로 간주
        /// </summary>
        private void DetectDuplicateRfidNodes()
        {
            _duplicateRfidNodes.Clear();

            if (_nodes == null || _nodes.Count == 0)
                return;

            // RFID값과 해당 노드의 인덱스를 저장
            var rfidToNodeIndex = new Dictionary<ushort, List<int>>();

            // 모든 노드의 RFID값 수집
            for (int i = 0; i < _nodes.Count; i++)
            {
                var node = _nodes[i];
                if (node.HasRfid())
                {
                    if (!rfidToNodeIndex.ContainsKey(node.RfidId))
                    {
                        rfidToNodeIndex[node.RfidId] = new List<int>();
                    }
                    rfidToNodeIndex[node.RfidId].Add(i);
                }
            }

            // 중복된 RFID를 가진 노드들을 찾아서 나중에 추가된 것들을 표시
            foreach (var kvp in rfidToNodeIndex)
            {
                if (kvp.Value.Count > 1)
                {
                    // 첫 번째 노드는 원본으로 유지, 나머지는 중복으로 표시
                    for (int i = 1; i < kvp.Value.Count; i++)
                    {
                        int duplicateNodeIndex = kvp.Value[i];
                        _duplicateRfidNodes.Add(_nodes[duplicateNodeIndex].Id);
                    }
                }
            }
        }

        /// <summary>
        /// 기존 노드들의 최대 번호를 찾아서 _nodeCounter를 업데이트
        /// </summary>
        private void UpdateNodeCounter()
        {
            if (_nodes == null || _nodes.Count == 0)
            {
                _nodeCounter = 1;
                return;
            }

            int maxNumber = 0;
            foreach (var node in _nodes)
            {
                // NodeId에서 숫자 부분 추출 (예: "N001" -> 1)
                if (node.Id.StartsWith("N") && int.TryParse(node.Id.Substring(1), out int number))
                {
                    maxNumber = Math.Max(maxNumber, number);
                }
            }

            _nodeCounter = maxNumber + 1;
        }

        /// <summary>
        /// 특정 노드에 도킹 오류 표시를 설정/해제합니다.
        /// </summary>
        /// <param name="nodeId">노드 ID</param>
        /// <param name="hasError">오류 여부</param>
        public void SetDockingError(string nodeId, bool hasError)
        {
            if (string.IsNullOrEmpty(nodeId))
                return;

            if (hasError)
            {
                _dockingErrors[nodeId] = true;
            }
            else
            {
                _dockingErrors.Remove(nodeId);
            }

            Invalidate(); // 화면 다시 그리기
        }

        /// <summary>
        /// 특정 노드에 도킹 오류가 있는지 확인합니다.
        /// </summary>
        /// <param name="nodeId">노드 ID</param>
        /// <returns>도킹 오류 여부</returns>
        public bool HasDockingError(string nodeId)
        {
            return _dockingErrors.ContainsKey(nodeId) && _dockingErrors[nodeId];
        }

        /// <summary>
        /// 모든 도킹 오류를 초기화합니다.
        /// </summary>
        public void ClearDockingErrors()
        {
            _dockingErrors.Clear();
            Invalidate();
        }

    }

}