using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.Utilities;
using MECF.Framework.Common.RecipeCenter;
using CyberX8_Core;
using CyberX8_RT.Devices.LinMot;
using CyberX8_RT.Devices.Prewet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
using MECF.Framework.Common.CommonData.Prewet;
using static CyberX8_RT.Modules.Prewet.PrewetKeepWetStateMachine;
namespace CyberX8_RT.Modules.Prewet
{
    public class PrewetProcessStateMachine : Entity, IEntity
    {
        #region 内部变量
        /// 
        /// 模块名称
        /// 
        private string _module;
        /// 
        /// prewet设备
        /// 
        private PrewetDevice _prewetDevice;
        /// 
        /// linmot axis
        /// 
        private LinMotAxis _linMotAxis;
        /// 
        /// Prewet recipe
        /// 
        private PwtRecipe _recipe;
        #endregion
        #region 属性
        /// 
        /// 状态
        /// 
        public string State { get { return ((PrewetProcessState)fsm.State).ToString(); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public PrewetProcessStateMachine(string module,LinMotAxis linMotAxis) 
        { 
            _module = module;
            _prewetDevice = DEVICE.GetDevice(module);
            _linMotAxis = linMotAxis;
            this.fsm = new StateMachine($"{module}_ProcessStateMachine", (int)PrewetProcessState.Idle, 10);
            fsm.EnableRepeatedMsg(true);
            AnyStateTransition(PrewetProcessMsg.Error, EnterError, PrewetProcessState.Error);
            Transition(PrewetProcessState.Error, PrewetProcessState.Process_Start, EnterProcessStartStatus, PrewetProcessState.Process_Start);
            Transition(PrewetProcessState.Idle, PrewetProcessMsg.ProcessStart, EnterProcessStartStatus, PrewetProcessState.Process_Start);
            Transition(PrewetProcessState.Process_Start,FSM_MSG.TIMER, NullFunc, PrewetProcessState.Process_StartScanning);
            Transition(PrewetProcessState.Process_StartScanning,FSM_MSG.TIMER, ProcessStartScan, WaitProcessStartStatus, PrewetProcessState.Process_WaitFirstScanComplete);
            Transition(PrewetProcessState.Process_WaitFirstScanComplete, FSM_MSG.TIMER, StartScan, PrewetProcessState.Process_WaitScanComplete);
            Transition(PrewetProcessState.Process_WaitScanComplete, FSM_MSG.TIMER, WaitScanComplete, PrewetProcessState.Process_Complete);
            Transition(PrewetProcessState.Process_Complete, FSM_MSG.TIMER, ProcessComplete, PrewetProcessState.Idle);
            EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
            EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
        }
        /// 
        /// 进入启动状态
        /// 
        /// 
        private bool EnterProcessStartStatus(object param)
        {
            object[] objects = param as object[];
            PwtRecipe pwtRecipe = (PwtRecipe)objects[0];
            if(pwtRecipe == null)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "recipe is null error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            _recipe = pwtRecipe;
            return true;
        }
        /// 
        /// 进入Error状态
        /// 
        /// 
        /// 
        private bool EnterError(object param)
        {
            if(_linMotAxis.Status==RState.Running)
            {
                _linMotAxis.AbortCurrentRoutine();
            }
            if(_prewetDevice.Status==RState.Running)
            {
                _prewetDevice.AbortCurrentRoutine();
            }
            return true;
        }
        #region process 
        /// 
        /// Process Start Scan
        /// 
        /// 
        private bool ProcessStartScan(object param)
        {
            bool result = _linMotAxis.ResetOperation("", false);
            if (!result)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "reset linmot error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            _prewetDevice.PrewetPumpData.PumpSpeedAuto = true;
            //更新Pump status状态
            string statusContent = _prewetDevice.PrewetPumpData.PumpStatus ? "On" : "Off";
            _prewetDevice.PrewetPumpData.PumpModel = "Auto";
            _prewetDevice.PrewetPumpData.PumpStatusContent = $"{_prewetDevice.PrewetPumpData.PumpModel}: {statusContent}";
            result = _prewetDevice.PumpSpeed();
            if(!result)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump speed error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            bool pumpEnableResult = _prewetDevice.PumpEnableOperation("", null);
            if (!pumpEnableResult)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump enable error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            return true;
        }
        /// 
        /// 等待start process状态
        /// 
        /// 
        private bool WaitProcessStartStatus(object param)
        {
            if(_prewetDevice.Status==RState.Failed)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "prewet device status is error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            if (_linMotAxis.Status == RState.Failed)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "linmot status is error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            if (_prewetDevice.Status == RState.End && _linMotAxis.Status == RState.End)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 开始Scan
        /// 
        /// 
        /// 
        private bool StartScan(object param)
        {
            if (!_linMotAxis.IsHomed)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "limot is not ready");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            if(!_prewetDevice.PrewetPumpData.PumpStatus)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump status if off");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            bool result = _linMotAxis.StartPosition("", new object[] { _recipe.NumberOfScans });
            if(!result)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "linmot start scan error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            return true;
        }
        /// 
        /// 等待Scan结束
        /// 
        /// 
        /// 
        private bool WaitScanComplete(object param)
        {
            if (_prewetDevice.PrewetPumpData.PumpFlowData.IsWarning)
            {
                LOG.WriteLog(eEvent.WARN_PREWET, _module, $"pump flow status {_prewetDevice.PrewetPumpData.PumpFlowData.Value}  is in warning");
            }
            if (_prewetDevice.PrewetPumpData.PumpFlowData.IsError)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, $"pump flow status {_prewetDevice.PrewetPumpData.PumpFlowData.Value} is in error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            if (_prewetDevice.PrewetPumpData.PumpPressureData.IsWarning)
            {
                LOG.WriteLog(eEvent.WARN_PREWET, _module, $"pump pressure status is {_prewetDevice.PrewetPumpData.PumpPressureData.Value} in warning");
            }
            if (_prewetDevice.PrewetPumpData.PumpPressureData.IsError)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, $"pump pressure status {_prewetDevice.PrewetPumpData.PumpPressureData.Value} is in error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            //linmot完成一次scan
            if (_linMotAxis.Status == RState.End)
            {
                return true;
            }
            if (_linMotAxis.Status == RState.Failed)
            {
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            return false;
        }
        /// 
        /// Process scan完成
        /// 
        /// 
        /// 
        private bool ProcessComplete(object param)
        {
            bool result = _prewetDevice.PumpDisableOperation("pump disable", null);
            if (!result)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump disable error");
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            result = _linMotAxis.SwitchOff();
            if (!result)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "linmot disable error");
                PostMsg(PrewetProcessMsg.Error);
                return false;
            }
            return true;
        }
        #endregion
        public bool Check(int msg, out string reason, params object[] args)
        {
            reason = "";
            return true;
        }
        public enum PrewetProcessState
        {
            Error,
            Idle,
            Process_Start,
            Process_StartScanning,
            Process_WaitFirstScanComplete,
            Process_WaitScanComplete,
            Process_Complete
        }
        public enum PrewetProcessMsg
        {
            Error,
            ProcessStart
        }
    }
}