using Autofac;
using Entity.Attr;
using Entity.Constant;
using HybirdFrameworkCore.Autofac;
using log4net;
using Repository.Station;
using Service.Execute.Api;
using Service.Execute.Model;
using Service.Execute.Model.Tbox;
using Service.Execute.StaticTools;
using Service.Execute.SwapException;
using Service.Execute.Utils;
using Service.Init;
using Service.Plc.Client;
using Service.Station;

namespace Service.Execute.Step;

public class DoSwappingState : IState
{
    private readonly ILog _log = LogManager.GetLogger(typeof(DoSwappingState));
    private readonly CommonMgr _CommonMgr = AppInfo.Container.Resolve<CommonMgr>();

    public StateResult Handle(SwappingStateMachine machine)
    {
        //上报云平台换电开始
        machine.BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.BeginSwap;
        machine.BusinessSwappingStateUpdateTime = DateTime.Now;
        _log.Info($"BusinessSwappingForCloudState={machine.BusinessSwappingForCloudState}");
        //   CloudApi.SendStateLog(machine.SwapOrder, InfoEnum.BusinessSwappingForCloudState.BeginSwap);


        //再次读锁止状态,防止plc需要挪车
        InvokeStatus carInPosition2 = CarInPosition2(machine);
        if (carInPosition2 != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(carInPosition2, ExceptionReason.None);
        }


        //下发启动换电
        InvokeStatus startSwapping = StartSwapping(machine);
        if (startSwapping != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(startSwapping, ExceptionReason.None);
        }

        InvokeStatus holdOn = HoldOn(machine);
        if (holdOn != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(holdOn, ExceptionReason.None);
        }


        //查看通道状态
        StateResult checkChannelStatus = CheckChannelStatus(machine);
        if (checkChannelStatus != null)
        {
            return checkChannelStatus;
        }

        //旧电池拆卸
        InvokeStatus unPack = UnPack(machine);
        if (unPack != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(unPack, ExceptionReason.None);
        }

        //旧电池搬运
        InvokeStatus oldBatteryCarryIn = OldBatteryCarryIn(machine);
        if (oldBatteryCarryIn != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(oldBatteryCarryIn, ExceptionReason.None);
        }

        //新电池搬运
        InvokeStatus newBatteryCarryOut = NewBatteryCarryOut(machine);
        if (newBatteryCarryOut != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(newBatteryCarryOut, ExceptionReason.None);
        }

        //安装
        InvokeStatus pack = Pack(machine);
        if (pack != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(pack, ExceptionReason.None);
        }

        //安装完成
        InvokeStatus packFinish = PackFinish(machine);
        if (packFinish != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(packFinish, ExceptionReason.None);
        }


        //航车回归安全位置
        InvokeStatus toInvokeStatus = ToSafePosition(machine);
        if (toInvokeStatus != InvokeStatus.Done)
        {
            return SwappingStateMachine.ReturnWithInvokeErr(toInvokeStatus, ExceptionReason.None);
        }
        //查询换电任务是否结束


        return new StateResult()
        {
            SwappingState = SwappingState.SwapDone
        };
    }

    /// <summary>
    /// 下发plc启动换电
    /// </summary>
    /// <returns></returns>
    public InvokeStatus StartSwapping(SwappingStateMachine machine)
    {
        return Invoker.Invoke("StartSwapping", 1000, 5, machine.IsCanceled,
            () => machine.StartSwappingFlag, () =>
            {
                Task<bool> result = TBoxApi.UnLockCarManyTimes(machine.RfidReadModel.VelVin);
                bool unLock = result.Result;
                if (unLock)
                {
                    //查询当前是否有任务执行

                    var readTaskNo = PlcMgr.PlcClient?.ReadTaskNo();
                    if (readTaskNo == 0 || readTaskNo == 1)
                    {
                        PlcMgr.PlcClient?.ExChangeTaskNo(1);
                        //查询车辆锁止状态
                        var startSwapping = PlcApi.StartSwapping(machine.SwapOrderBatteryInfo.InBinInfo.No,
                            machine.SwapOrderBatteryInfo.UpBinInfo.No);

                        //查詢當前任務狀態是否被更改
                        var readPlcTaskStatus = PlcApi.ReadTaskStatus(1);
                        if (startSwapping && readPlcTaskStatus)
                        {
                            machine.SwapOrder.SwapBeginTime = DateTime.Now;
                            _CommonMgr.UpdateSwapOrder(machine);
                            machine.SwapStatus = 0;
                            machine.StartSwappingFlag = true;
                            _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.StartSwappingFlag,
                                machine);
                        }
                    }
                    else
                    {
                        _log.Info("当前有任务在执行");
                    }
                }
            }, () => { SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrStartSwap); }, false, () => { }, 10,
            InvokeStatus.None);
    }


    /// <summary>
    /// plc读任务状态 上使能
    /// </summary>
    /// <param name="machine"></param>
    /// <returns></returns>
    public InvokeStatus HoldOn(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc HoldOn", 1000, 5, machine.IsCanceled,
            () => machine.PlcHoldFlag, () =>
            {
                //查询车辆锁止状态
                var taskPrepare = PlcApi.ReadTaskStatus(1);
                if (taskPrepare)
                {
                    bool holdOn = PlcApi.HoldOn();
                    if (holdOn)
                    {
                        SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.StartSwapInfo);
                        machine.PlcHoldFlag = true;
                    }
                }
            }, () => { });
    }


    /// <summary>
    /// 读取plc任务状态电池拆卸中
    /// 读取plc任务状态电池入库搬运中
    ///   读取plc任务状态电池出库搬运中
    /// 读取plc任务状态电池安装中
    ///  读取plc任务状态电池安装完成
    /// </summary>
    /// <returns></returns>
    public InvokeStatus UnPack(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc UnPack", 500, 5, machine.IsCanceled,
            () => machine.UnOldBatteryFlag, () =>
            {
                //   machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoUnPack.GetLed());


                int status = PlcApi.ReadPlcTaskStatus();
                //处理程序太快,plc还没有初始值的状态
                if (status == 1002 || status != 1003)
                {
                }
                else
                {
                    machine.UnOldBatteryFlag = true;
                }

                if (machine.UnOldBatteryFlag)
                {
                    _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.UnOldBatteryFlag,
                        machine);
                }
            }, () => { SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoUnPack); }, false, () => { }, 10,
            InvokeStatus.None);
    }

    public InvokeStatus OldBatteryCarryIn(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc OldBatteryCarryIn", 500, 5, machine.IsCanceled,
            () => machine.StorageOldBatteryFlag, () =>
            {
                //  machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoOldBatteryCarryIn.GetLed());
                var readPlcTaskStatus = PlcApi.ReadPlcTaskStatus();

                if (readPlcTaskStatus == 1003 || readPlcTaskStatus != 1004)
                {
                }
                else
                {
                    machine.StorageOldBatteryFlag = true;
                }

                machine.StorageOldBatteryFlag = readPlcTaskStatus == 1004;

                if (machine.StorageOldBatteryFlag)
                {
                    _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.StorageOldBatteryFlag,
                        machine);
                }
            }, () => { SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoOldBatteryCarryIn); }, false, () => { }, 10,
            InvokeStatus.None);
    }

    public InvokeStatus NewBatteryCarryOut(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc NewBatteryCarryOut", 500, 5, machine.IsCanceled,
            () => machine.OutNewBatteryFlag, () =>
            {
                // machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoNewBatteryCarryOut.GetLed());

                if (PlcApi.ReadPlcTaskStatus() == 1004)
                {
                }
                else
                {
                    machine.OutNewBatteryFlag = true;
                }

                if (machine.OutNewBatteryFlag)
                {
                    _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.OutNewBatteryFlag,
                        machine);
                }
            }, () => { SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoNewBatteryCarryOut); }, false, () => { }, 10,
            InvokeStatus.None);
    }


    public InvokeStatus Pack(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc Pack ing", 500, 5, machine.IsCanceled,
            () => machine.InstallNewBatteryFlag, () =>
            {
                // machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoPack.GetLed());
                if (PlcApi.ReadPlcTaskStatus() == 1005)
                {
                }
                else
                {
                    machine.InstallNewBatteryFlag = true;
                }

                if (machine.InstallNewBatteryFlag)
                {
                    _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.InstallNewBatteryFlag,
                        machine);
                }
            }, () => { SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoPack); }, false, () => { },
            10, InvokeStatus.None);
    }

    public InvokeStatus PackFinish(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc Pack Finish", 500, 5, machine.IsCanceled,
            () => machine.FinishNewBatteryFlag, () =>
            {
                //  machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoPackFinish.GetLed());
                var readPlcTaskStatus = PlcApi.ReadPlcTaskStatus();
                if (readPlcTaskStatus == 1006 || readPlcTaskStatus == 1007)
                {
                    machine.FinishNewBatteryFlag = true;
                    machine.BusinessSwappingForCloudState =
                        InfoEnum.BusinessSwappingForCloudState.SwapFinish;
                    //  CloudApi.SendStateLog(machine.SwapOrder, machine.BusinessSwappingForCloudState);
                    machine.BusinessSwappingStateUpdateTime = DateTime.Now;
                    SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoPackFinish);

                    _CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.FinishNewBatteryFlag,
                        machine);
                }
            }, () => { }, false, () => { },
            10, InvokeStatus.None);
    }

    /// <summary>
    /// 行车回归安全位置
    /// </summary>
    /// <param name="machine"></param>
    /// <returns></returns>
    public InvokeStatus ToSafePosition(SwappingStateMachine machine)
    {
        return Invoker.Invoke("plc ToSavePosition", 500, 5, machine.IsCanceled,
            () => machine.ToSafePositionFlag, () =>
            {
                //  machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoPackFinish.GetLed());

                if (PlcApi.ReadPlcTaskStatus() == 1007)
                {
                    SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoToSafePosition);
                    machine.ToSafePositionFlag = true;
                    machine.BusinessSwappingStateUpdateTime = DateTime.Now;

                    machine.SwapStatus = 1;
                }
            }, () => { });
    }


    /// <summary>
    /// 查看通道状态
    /// :0:无效值
    /// 1000;拍照OK
    ///1010;拍照NG
    ///1020;拍照超限,请移车
    /// </summary>
    /// <returns></returns>
    public StateResult CheckChannelStatus(SwappingStateMachine machine)
    {
        int count = 0;
        while (!machine.ChannelStatusOkFlag)
        {
            if (machine.CancelFlag)
            {
                _log.Info($" CheckChannelStatus canceled");
                return StateResult.Cancel;
            }

            _log.Info("begin plc CheckChannelStatus");
            Thread.Sleep(2000);
            var channelStatus = PlcApi.ChannelStatus();
            if (count % 10 == 0)
            {
                SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.CarTakePhotoInfo);
            }

            count++;

            if (channelStatus == 1000)
            {
                machine.ChannelStatusOkFlag = true;
                return null;
            }
            else if (channelStatus == 1020)
            {
                //需要移车 先解锁  提示移动车辆,等待3分钟
                var lockCar = TBoxApi.LockCarManyTimes(machine.RfidReadModel.VelVin);
                if (lockCar.Result)
                {
                    // machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrChannelStatus.GetLed());
                    SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrChannelStatus);
                    //等待2分钟
                    Thread.Sleep(3 * 60 * 1000);
                    machine.VehiclesInPlace2Flag = false;
                    machine.StartSwappingFlag = false;
                    machine.PlcHoldFlag = false;
                    machine.ChannelStatusOkFlag = false;
                    //回归到本阶段的读锁止状态
                    return new StateResult()
                    {
                        SwappingState = SwappingState.DoSwapping
                    };
                }
            }
            else if (channelStatus == 1010)
            {
                //故障 不能继续换电,提示驶离,上报云平台,修改换电订单
                machine.SwapStatus = (int)InfoEnum.SwapOrderResult.Fail;
                machine.SwapFailReason = "拍照故障 plc故障码1010";
                //跳转到SwappDone
                return new StateResult()
                {
                    SwappingState = SwappingState.SwapDone
                };
            }
        }

        return null;
    }


    /// <summary>
    /// 车辆到位
    /// </summary>
    /// <returns></returns>
    public InvokeStatus CarInPosition2(SwappingStateMachine machine)
    {
        return Invoker.Invoke("check CarInPosition2", 500, 50, machine.IsCanceled,
            () => machine.VehiclesInPlace2Flag, () =>
            {
                var result = TBoxApi.GetCarInfo(machine.RfidReadModel.VelVin);
                TboxCarInfoModel tboxCarInfoModel = result.Result;

                int succCount = 0;
                List<bool> succL = new List<bool>()
                {
                    StaticStationInfo.TboxStateFlameout, StaticStationInfo.TboxStateBreak, StaticStationInfo.TboxStateN
                };
                var successCount = succL.Where(i => i).Count();

                var status = tboxCarInfoModel?.CarStatus;

                if (StaticStationInfo.TboxStateFlameout)
                {
                    if (status?.Keys == 0)
                    {
                        succCount++;
                    }
                }

                if (StaticStationInfo.TboxStateBreak)
                {
                    if (status?.Break == 1)
                    {
                        succCount++;
                    }
                }

                if (StaticStationInfo.TboxStateN)
                {
                    if (status?.Gear == 0)
                    {
                        succCount++;
                    }
                }

                if (succCount == successCount)
                {
                    machine.VehiclesInPlace2Flag = true;
                }
            }, () =>
            {
                machine.ExceptionReason = ExceptionReason.CarInPositionError;
                //   machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed());
                SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout);
            }, false, () => { }
            , 20, InvokeStatus.None);
    }
}