using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Project.StateMachine;
using COMM;
using AR;
using AGVNavigationCore.Models;

namespace Project.ViewForm
{
    public partial class fAuto : Form
    {

        public fAuto()
        {
            InitializeComponent();
            this.FormClosed += FAuto_FormClosed;
            PUB.sm.StepChanged += Sm_StepChanged;
            this.ctlAuto1.ButtonClick += CtlAuto1_ButtonClick;
            if (PUB.sm.Step == eSMStep.INIT || PUB.sm.Step == eSMStep.SYNC)
                this.ctlAuto1.Scean = CtlAuto.eScean.Progress;
            else
                this.ctlAuto1.Scean = CtlAuto.eScean.Normal;

            InitializeMapCanvas();

        }

        private void InitializeMapCanvas()
        {
            PUB._mapCanvas.NodeSelect += OnNodeSelected; ;
            // 스플리터 패널에 맵 캔버스 추가
            panel1.Controls.Add(PUB._mapCanvas);
        }


        private void OnNodeSelected(object sender, NodeBase node, MouseEventArgs e)
        {
            if (node == null) return;
            var mapnode = node as MapNode;
            if (mapnode == null) return;

            // [Run Mode] Left Click: AGV Operation
            if (PUB._mapCanvas.Mode == AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run && e.Button == MouseButtons.Left)
            {
                HandleRunModeClick(mapnode);
                return;
            }

            if (e.Button != MouseButtons.Right) return;

            // 도킹 가능한 노드인지 또는 작업 노드인지 확인
            if (mapnode.isDockingNode == false) return;

            ContextMenuStrip menu = new ContextMenuStrip();

            // Goto
            var cmdGoto = new ToolStripMenuItem("Goto");
            cmdGoto.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.Goto);
            menu.Items.Add(cmdGoto);

            // PickOn
            var pickOn = new ToolStripMenuItem("Pick On (Move & Pick)");
            pickOn.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.PickOnEnter);
            menu.Items.Add(pickOn);

            // PickOff
            var pickOff = new ToolStripMenuItem("Pick Off (Move & Drop)");
            pickOff.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.PickOffEnter);
            menu.Items.Add(pickOff);

            // Charge
            if (mapnode.StationType == Station.Charger )
            {
                var charge = new ToolStripMenuItem("Charge (Move & Charge)");
                charge.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.Charger);
                menu.Items.Add(charge);
            }

            menu.Show(Cursor.Position);



        }

        private void ExecuteManualCommand(MapNode targetNode, ENIGProtocol.AGVCommandHE cmd)
        {
            if (PUB._virtualAGV.CurrentNode == null)
            {
                MessageBox.Show("AGV의 현재 위치를 알 수 없습니다.");
                return;
            }
            if (PUB.sm.Step == eSMStep.IDLE)
            {
                if (MessageBox.Show("현재 대기상태가 아닙니다. 강제로 실행하시겠습니까?", "Warning", MessageBoxButtons.YesNo) == DialogResult.No) return;
            }

            if (targetNode.isDockingNode == false)
            {
                UTIL.MsgE("이동 가능한 노드가 아닙니다");
            }

            // 1. 경로 생성
            var pathFinder = new AGVNavigationCore.PathFinding.Planning.AGVPathfinder(PUB._mapCanvas.Nodes);

            //// 현재위치에서 목표위치까지
            //var result = pathFinder.FindBasicPath(PUB._virtualAGV.CurrentNode, targetNode);

            //if (!result.Success || result.Path == null || result.Path.Count == 0)
            //{
            //    MessageBox.Show("경로를 찾을 수 없습니다.");
            //    return;
            //}

            // 2. 상태 설정

            // 2. 상태 설정
            if (targetNode is MapNode mapno)
                PUB.log.AddI($"[Manual Command] {cmd} to {mapno.RfidId}({targetNode.Id})");
            else
                PUB.log.AddI($"[Manual Command] {cmd} to ({targetNode.Id})");

            // FindPathResult contains DetailedPath already.
            // PUB._virtualAGV.SetPath(result);
            PUB._virtualAGV.TargetNode = targetNode as MapNode;

            // 3. 작업 설정
            PUB.NextWorkCmd = cmd;

            // 4. 실행
            PUB.sm.SetNewRunStep(ERunStep.GOTO); // GOTO -> Arrive -> _IN sequence execution
        }


        private void fAuto_Load(object sender, EventArgs e)
        {
            ctlAuto1.dev_agv = PUB.AGV;
            ctlAuto1.dev_bms = PUB.BMS;
            ctlAuto1.dev_xbe = PUB.XBE;

            PUB.AGV.DataReceive += AGV_DataReceive;


        }
        private void AGV_DataReceive(object sender, arDev.Narumi.DataEventArgs e)
        {
            switch (e.DataType)
            {
                case arDev.Narumi.DataType.TAG:
                    //_AGV 파일에서 위치조정을 함
                    //var tagno = PUB.AGV.data.TagNo;                    
                    //PUB.mapctl.SetCurrentPosition(tagno);
                    break;
            }
        }

        private void CtlAuto1_ButtonClick(CtlAuto.UIButton idx)
        {
            if (idx.cmd.Equals("EMG"))
            {
                PUB.log.Add("ui reset click");
                PUB.AGV.AGVErrorReset();
            }
        }

        private void Sm_StepChanged(object sender, StateMachine.StateMachine.StepChangeEventArgs e)
        {
            if (e.New == eSMStep.INIT || e.New == eSMStep.SYNC)
                this.ctlAuto1.Scean = CtlAuto.eScean.Progress;
            else
                this.ctlAuto1.Scean = CtlAuto.eScean.Normal;
        }

        private void FAuto_FormClosed(object sender, FormClosedEventArgs e)
        {
            timer1.Stop();
            PUB.sm.StepChanged -= Sm_StepChanged;
            this.ctlAuto1.ButtonClick -= CtlAuto1_ButtonClick;
            PUB.AGV.DataReceive -= AGV_DataReceive;
        }

        bool tmrun = false;

        private void fAuto_VisibleChanged(object sender, EventArgs e)
        {
            this.timer1.Enabled = this.Visible;
            if (timer1.Enabled)
            {
                timer1.Start();
            }
            else timer1.Stop();
        }

        private void timer1_Tick_1(object sender, EventArgs e)
        {

        }

        private void HandleRunModeClick(MapNode targetNode)
        {
            if (targetNode == null) return;

            ENIGProtocol.AGVCommandHE targetCmd = ENIGProtocol.AGVCommandHE.Goto;
            string confirmMsg = "";

            if (targetNode.StationType == Station.Charger)
            {
                if (MessageBox.Show($"[{targetNode.Id}] 충전기로 이동하여 충전을 진행하시겠습니까?", "작업 확인", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    targetCmd = ENIGProtocol.AGVCommandHE.Charger;
                    ExecuteManualCommand(targetNode, targetCmd);
                }
                return;
            }
            else if (targetNode.isDockingNode)
            {
                // Loader, Unloader, Buffer, Cleaner - Pick/Drop Selection
                ContextMenuStrip menu = new ContextMenuStrip();

                var pickOn = new ToolStripMenuItem("Pick On (Move & Pick)");
                pickOn.Click += (s, args) => ExecuteManualCommand(targetNode, ENIGProtocol.AGVCommandHE.PickOnEnter);
                menu.Items.Add(pickOn);

                var pickOff = new ToolStripMenuItem("Pick Off (Move & Drop)");
                pickOff.Click += (s, args) => ExecuteManualCommand(targetNode, ENIGProtocol.AGVCommandHE.PickOffEnter);
                menu.Items.Add(pickOff);

                menu.Show(Cursor.Position);
                return;
            }
            else
            {
                // Normal Node
                if (MessageBox.Show($"[{targetNode.Id}] 노드로 이동하시겠습니까?", "이동 확인", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    targetCmd = ENIGProtocol.AGVCommandHE.Goto;
                    ExecuteManualCommand(targetNode, targetCmd);
                }
                return;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            if (this.Visible == false) return;
            if (tmrun == true) return;
            if (PUB.sm.Step < eSMStep.IDLE) return;
            if (PUB._mapCanvas == null) return;
            tmrun = true;


            var errmsg = string.Empty;
            if (PUB.AGV.IsOpen == false)
            {
                errmsg = "AGV컨트롤러 연결실패";
            }
            else if (PUB.XBE.IsOpen == false)
            {
                errmsg = "XBEE 연결실패";
            }
            else if (PUB.XBE.senderrcnt > 5)
            {
                errmsg = "XBEE 통신불가";
            }
            else if (PUB.AGV.error.Value > 0)
            {
                errmsg = PUB.AGV.error.ToString();
            }
            else if (PUB.AGV.system1.stop_by_front_detect)
            {
                errmsg = "전방 물체감지로 인해 정지";
            }
            else if (PUB.BMS.IsOpen == false)
            {
                errmsg = "BMS 연결실패";
            }
            else if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false)
            {
                errmsg = "자동모드가 아닙니다";
            }

            PUB._mapCanvas.SetSystemMessage(errmsg);
            tmrun = false;
        }

        private void fAuto_Load_1(object sender, EventArgs e)
        {
            this.timer1.Start();
        }
    }
}
