using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;

namespace Project
{
    public partial class fMain
    {
        DateTime tm_gocharge_command = DateTime.Now;
        public Boolean _SM_RUN_CHARGE_ON(bool isFirst, TimeSpan stepTime)
        {
            var funcname = "GOCHARGE";
            if (runStepisFirst)
            {
                //홈을 찾도록 항상 위치를 지워버리자
                PUB.Result.CurrentPos = ePosition.NONE;
            }

            //HW 연결오류
            if (PUB.AGV.IsOpen == false)
            {
                PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR);
                return false;
            }

            //이미 충전중이라면 바로 완료 처리한다 (사용자 요청)
            if (VAR.BOOL[eVarBool.FLAG_CHARGEONA] == true || 
                PUB.AGV.system1.Battery_charging == true ||
                VAR.BOOL[eVarBool.FLAG_CHARGEONM] == true)
            {
                SetRunStepError(ENIGProtocol.AGVErrorCode.ALREADY_CHARGE);
                return false;
            }

            //충전 상태가 OFF되어야 동작하게한다
            if (_SM_RUN_CHARGE_OFF(isFirst, stepTime) == false)
                return false;


            //라이더멈춤이 설정되어있다면 음성으로 알려준다 200409
            if (PUB.AGV.system1.stop_by_front_detect == true)
            {
                var tsSpeak = DateTime.Now - LastSpeakTime;
                if (tsSpeak.TotalSeconds >= PUB.setting.alarmSoundTerm)
                {
                    PUB.Speak(Lang.전방에물체가감지되었습니다);
                    LastSpeakTime = DateTime.Now;
                }
                return false;
            }

            var idx = 1;
            if (PUB.sm.RunStepSeq == idx++)
            {
                var targetnode = PUB.FindByRFID(PUB.setting.NodeMAP_RFID_Charger);
                if (targetnode == null)
                {
                    SetRunStepError(ENIGProtocol.AGVErrorCode.NOTSET_CHARGEPOINT);
                    return false;
                }

                //현재위치가 충전기위치이고 마크센서가 감지되었다면 충전기위치로 인지하고
                //그렇지 못하면 충전위치가 아니라는 오류를 발생한다
                var curnode = PUB._virtualAGV.CurrentNode;
                if (curnode.Id != targetnode.Id)
                {
                    SetRunStepError(ENIGProtocol.AGVErrorCode.NO_CHARGEPOINT, $"충전기위치가 아니므로 충전을 시작할 수 없습니다(현재위치:{curnode.RfidId})");
                    return false;
                }

                //마크센서가 들어와있어야한다
                if (PUB.AGV.signal1.mark_sensor == false)
                {
                    SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_SENSOR_FAIL, $"충전기위치에서 마크센서가 확인되지 않습니다");
                    return false;
                }

                PUB.sm.UpdateRunStepSeq();
                return false;
            }
            else if (PUB.sm.RunStepSeq == idx++)
            {
                //충전시작 명령을 전송한다
                PUB.log.Add($"충전:충전명령전송");
                PUB.logdebug.Add($"[AI_TRACE] {funcname} Step {PUB.sm.RunStepSeq}: Sending Charge Start Command to ChargerID={PUB.setting.ChargerID}");
                PUB.Speak(Lang.충전시작명령을전송합니다);
                PUB.AGV.AGVCharge(PUB.setting.ChargerID, true);
                VAR.BOOL[eVarBool.WAIT_CHARGEACK] = true;
                LastCommandTime = DateTime.Now;
                VAR.BYTE[eVarByte.CHARGE_CMDCNT] = 0;
                PUB.sm.UpdateRunStepSeq();
                return false;
            }
            //충전시작명령의 ACK를 체크합니다
            else if (PUB.sm.RunStepSeq == idx++)
            {
                //충전시작 명령을 전송한다
                if (PUB.AGV.ACKData.Equals("CBT"))
                {
                    PUB.log.Add($"충전명령 회신 확인");
                    PUB.logdebug.Add($"[AI_TRACE] {funcname} Step {PUB.sm.RunStepSeq}: Charge Command ACK Received (CBT)");
                    PUB.sm.UpdateRunStepSeq();
                }
                else
                {
                    var ts = DateTime.Now - LastCommandTime;
                    if (ts.TotalSeconds > 3)
                    {
                        if (VAR.BYTE[eVarByte.CHARGE_CMDCNT] > 5)
                        {
                            PUB.counter.CountChargeE += 1;
                            PUB.counter.Save();
                            VAR.BYTE[eVarByte.CHARGE_CMDCNT] = 0;

                            SetRunStepError(ENIGProtocol.AGVErrorCode.CHARGE_RETRY_OVER);
                            return false;
                        }
                        else
                        {
                            PUB.logagv.Add($"충전시작명령 재전송");
                            VAR.BYTE.Add(eVarByte.CHARGE_CMDCNT, 1);
                            PUB.AGV.AGVCharge(PUB.setting.ChargerID, true);
                            LastCommandTime = DateTime.Now;
                        }
                    }
                }
                return false;
            }
            return true;
        }
    }
}
