using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.Utilities;
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;

namespace CyberX8_RT.Modules.Prewet
{
    public class PrewetKeepWetStateMachine : Entity, IEntity
    {
        #region 内部变量
        /// <summary>
        /// 模块名称
        /// </summary>
        private string _module;
        /// <summary>
        /// prewet设备
        /// </summary>
        private PrewetDevice _prewetDevice;
        /// <summary>
        /// linmot axis
        /// </summary>
        private LinMotAxis _linMotAxis;
        #endregion


        #region 属性
        /// <summary>
        /// 状态
        /// </summary>
        public string State { get { return ((PrewetKeepWetState)fsm.State).ToString(); } }
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="module"></param>
        public PrewetKeepWetStateMachine(string module,LinMotAxis linMotAxis) 
        { 
            _module = module;
            _prewetDevice = DEVICE.GetDevice<PrewetDevice>(module);
            _linMotAxis = linMotAxis;          
            fsm = new StateMachine($"{_module}_KeepWetStateMachine", (int)PrewetKeepWetState.Idle, 20);
            fsm.EnableRepeatedMsg(true);
            AnyStateTransition(PrewetKeepWetMsg.ReturnIdle, NullFunc, PrewetKeepWetState.Idle);
            AnyStateTransition(PrewetKeepWetMsg.Error, EnterError, PrewetKeepWetState.Error);
            Transition(PrewetKeepWetState.Error, PrewetKeepWetMsg.KeepWetStart, NullFunc, PrewetKeepWetState.Idle_KeepwetPrepare);
            Transition(PrewetKeepWetState.Idle, PrewetKeepWetMsg.KeepWetStart, NullFunc, PrewetKeepWetState.Idle_KeepwetPrepare);
            Transition(PrewetKeepWetState.Idle_KeepwetPrepare, FSM_MSG.TIMER, ResetLinmot, CheckResetLinmot, PrewetKeepWetState.Idle_KeepWetStart);
            Transition(PrewetKeepWetState.Idle_KeepWetStart, FSM_MSG.TIMER, ExecuteWetScan, WaitExecuteWetScan, PrewetKeepWetState.Idle_KeepWetScan);
            Transition(PrewetKeepWetState.Idle_KeepWetScan, FSM_MSG.TIMER, KeepWetComplete, PrewetKeepWetState.Idle_KeepWetPause);
            Transition(PrewetKeepWetState.Idle_KeepWetPause, FSM_MSG.TIMER, NullFunc, PrewetKeepWetState.Idle);

            EnumLoop<PrewetKeepWetState>.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });

            EnumLoop<PrewetKeepWetMsg>.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
        }


        /// <summary>
        /// 初始化
        /// </summary>
        protected override bool Init()
        {
            fsm.Init((int)PrewetKeepWetState.Idle, 20);
            return true;
        }
        /// <summary>
        /// 进入Error状态
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool EnterError(object param)
        {
            if(_linMotAxis.Status==RState.Running)
            {
                _linMotAxis.AbortCurrentRoutine();
            }
            if(_prewetDevice.Status==RState.Running)
            {
                _prewetDevice.AbortCurrentRoutine();
            }
            return true;
        }
        #region process 
        /// <summary>
        /// Reset Linmot
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool ResetLinmot(object param)
        {
            bool result = _linMotAxis.ResetOperation("", false);
            if (!result)
            {
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            return true;
        }
        /// <summary>
        /// 检验Reset Linmot状态
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool CheckResetLinmot(object param)
        {
            if (_linMotAxis.Status == RState.End)
            {
                return true;
            }
            else if(_linMotAxis.Status==RState.Failed)
            {
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            return false;
        }
        /// <summary>
        /// execute Keep Wet Scan
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool ExecuteWetScan(object param)
        {
            bool pumpValveResult = _prewetDevice.PumpValveOpen();
            if (!pumpValveResult)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump valve open error");
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }

            //bool pumpEnableResult = _prewetDevice.PumpEnableOperation("", null);
            bool pumpEnableResult = _prewetDevice.PumpEnable();
            if (!pumpEnableResult)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump enable error");
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            bool result = _linMotAxis.StartPosition("", new object[] { 1 });
            if (!result)
            {
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            return true;
        }
        /// <summary>
        /// Wait execute WetScan
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool WaitExecuteWetScan(object param)
        {
            if (_prewetDevice.PrewetPumpData.PumpFlowData.IsWarning)
            {
                LOG.WriteLog(eEvent.WARN_PREWET, _module, "pump flow status is in warning");
            }
            if (_prewetDevice.PrewetPumpData.PumpFlowData.IsError)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump flow status is in error");
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            if (_prewetDevice.PrewetPumpData.PumpPressureData.IsWarning)
            {
                LOG.WriteLog(eEvent.WARN_PREWET, _module, "pump pressure status is in warning");
            }
            if (_prewetDevice.PrewetPumpData.PumpPressureData.IsError)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, _module, "pump pressure status is in error");
                PostMsg(PrewetKeepWetMsg.Error);
                return false;
            }
            //linmot完成一次scan
            if ( _linMotAxis.Status == RState.End)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// Keep wet scan完成
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool KeepWetComplete(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(PrewetKeepWetMsg.Error);
                return false;
            }
            return true;
        }
        #endregion
        public bool Check(int msg, out string reason, params object[] args)
        {
            reason = "";
            return true;
        }

        public enum PrewetKeepWetState
        {
            Error,
            Idle,
            Idle_KeepwetPrepare,
            Idle_KeepWetStart,
            Idle_KeepWetScan,
            Idle_KeepWetPause
        }

        public enum PrewetKeepWetMsg
        {
            Error,
            KeepWetStart,
            ReturnIdle
        }
    }
}