using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData.Loader;
using MECF.Framework.Common.TwinCat;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS.CANOpen;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Loader
{
    public class LoaderSideDevice : BaseDevice, IDevice
    {
        /// 
        /// 
        /// 
        private enum LoaderSideOperation
        {
            None,
            DoorOn,
            DoorOff,
            VacuumOn,
            VacuumOff,
            WhBladderOn,
            WhBladderOff,
            TransBladderOn,
            TransBladderOff,
            TransHighOn,
            TransHighOff,
            BernoulliBladderOn,
            BernoulliBladderOff,
            BernoulliN2On,
            BernoulliN2Off,
            Load,
            Unload,
            InstallCRS,
            StartCycle,
            StopCycle
        }
        #region 常量
        private const string WAFER_PRESENT = "WaferPresent";
        private const string DOOR_UNLOCK = "DoorUnlock";
        private const string DOOR_UPPER_LOCKED = "DoorUpperLocked";
        private const string DOOR_UPPER_UNLOCKED = "DoorUpperUnlocked";
        private const string DOOR_LOWER_LOCKED = "DoorLowerLocked";
        private const string DOOR_LOWER_UNLOCKED = "DoorLowerUnlocked";
        private const string CRS_VACUUM="CRSVacuum";
        private const string CRS_VACUUM_VALUE = "CRSVacuumValue";
        private const string WH_BLADDER = "WHBladder";
        private const string WH_BLADDER_PRESSURE="WHBladderPressure";
        private const string TRANS_BLADDER="TransBladder";
        private const string TRANS_HIGH="TransHigh";
        private const string TRANS_RETRACTED="TransRetracted";
        private const string TRANS_PRESSURE = "TransPressure";
        private const string BERNOULLI_BLADDER= "BernoulliBladder";
        private const string BERNOULLI_EXTENDED="BernoulliExtended";
        private const string BERNOULLI_N2="BernoulliN2";
        private const string BERNOULLI_N2_SECOND = "BernoulliN2Second";
        private const string BERNOULLI_PRESSURE="BernoulliPressure";
        private const string WAFER_HOLDER_LOCKED = "WaferHolderLocked";
        private const string BERNOULLI_BLADDER_PRESSURE="BernoulliBladderPressure";
        private const string SIDE_DATA = "SideData";
        private const string CURRENT_OPERATION = "CurrentOperation";
        #endregion
        #region 内部变量
        /// 
        /// 数据
        /// 
        private LoaderSideData _siderData=new LoaderSideData();
        /// 
        /// 状态
        /// 
        private RState _status;
        /// 
        /// 当前操作
        /// 
        private LoaderSideOperation _currentOperation;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 当前次数
        /// 
        private string _currentCycle = "";
        #region routine
        /// 
        /// door lock routine
        /// 
        private LoaderSideDoorLockRoutine _doorlockRoutine;
        /// 
        /// Vacuum Routine
        /// 
        private LoaderSideVacuumRoutine _vacuumRoutine;
        /// 
        /// WH Bladder Routine
        /// 
        private LoaderSideWhBladderRoutine _whBladderRoutine;
        /// 
        /// Bernoulli Bladder Routine
        /// 
        private LoaderSideBernoulliBladderRoutine _bernoulliBladderRoutine;
        /// 
        /// Load Routine
        /// 
        private LoaderLoadRoutine _loadRoutine;
        /// 
        /// Unload Routine
        /// 
        private LoaderUnloadRoutine _unloadRoutine;
        /// 
        /// Install Routine
        /// 
        private LoaderInstallCRSRoutine _installCRSRoutine;
        /// 
        /// Cycle Routine
        /// 
        private LoaderSideCycleRoutine _cycleRoutine;
        #endregion
        #endregion
        #region 属性
        /// 
        /// 数据
        /// 
        public LoaderSideData SideData
        {
            get { return _siderData; }
            set { _siderData = value; }
        }
        /// 
        /// 状态
        /// 
        public RState Status { get { return _status; } }
        /// 
        /// 当前次数
        /// 
        public String CurrentCycle { get { return _currentCycle; } }
        /// 
        /// 所有io变量是否初始化
        /// 
        public bool IOInitialized { get { return IOVariableDictionaryUtil.AllIoVariableInitialized(eEvent.ERR_LOADER,Module,_variableInitializeDic); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public LoaderSideDevice(string moduleName,string name):base(moduleName,name,name,name)
        {
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            SubscribeData();
            SubscribeValueAction();
            InitializeRoutine();
            InitializeOperation();
            return true;
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _doorlockRoutine = new LoaderSideDoorLockRoutine($"{Module}.{Name}");
            _vacuumRoutine = new LoaderSideVacuumRoutine($"{Module}.{Name}");
            _whBladderRoutine = new LoaderSideWhBladderRoutine($"{Module}.{Name}");
            _bernoulliBladderRoutine = new LoaderSideBernoulliBladderRoutine($"{Module}.{Name}");
            _loadRoutine = new LoaderLoadRoutine(Module,Name);
            _unloadRoutine = new LoaderUnloadRoutine(Module,Name);
            _installCRSRoutine = new LoaderInstallCRSRoutine(Module,Name);
            _cycleRoutine = new LoaderSideCycleRoutine(Module, Name);
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            DATA.Subscribe($"{Module}.{Name}.{SIDE_DATA}", () => _siderData,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.CurrentCycle", () => _currentCycle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.CurrentCycleStep", () => 
            {
                if(_currentOperation==LoaderSideOperation.StartCycle)
                {
                    return _cycleRoutine.CurrentStep;
                }
                else
                {
                    return "";
                }
            }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.{CURRENT_OPERATION}", () => _currentOperation.ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.CRSVacuumValue",()=>_siderData.CRSVacuumValue, SubscriptionAttribute.FLAG.IgnoreSaveDB); 
            DATA.Subscribe($"{Module}.{Name}.CRSVacuum", () => _siderData.CRSVacuum, SubscriptionAttribute.FLAG.IgnoreSaveDB); 
            DATA.Subscribe($"{Module}.{Name}.BernoulliPressure", () => _siderData.BernoulliPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.BernoulliBladder", () => _siderData.BernoulliBladder, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.BernoulliBladderPressure", () => _siderData.BernoulliBladderPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.BernoulliExtended", () => _siderData.BernoulliExtended, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.BernoulliN2", () => _siderData.BernoulliN2, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.BernoulliN2Second", () => _siderData.BernoulliN2Second, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.DoorLowerLocked", () => _siderData.DoorLowerLocked, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.DoorLowerUnlocked", () => _siderData.DoorLowerUnlocked, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.DoorUpperLocked", () => _siderData.DoorUpperLocked, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.DoorUpperUnlocked", () => _siderData.DoorUpperUnlocked, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.TransBladder", () => _siderData.TransBladder, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.TransHigh", () => _siderData.TransHigh, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.TransPressure", () => _siderData.TransPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.TransRetracted", () => _siderData.TransRetracted, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.WaferPresent", () => _siderData.WaferPresent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.WSBladder", () => _siderData.WHBladder, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{Name}.WSBladderPressure", () => _siderData.WHBladderPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(WAFER_PRESENT);
            BeckhoffIoSubscribeUpdateVariable(DOOR_UNLOCK);
            BeckhoffIoSubscribeUpdateVariable(DOOR_UPPER_LOCKED);
            BeckhoffIoSubscribeUpdateVariable(DOOR_UPPER_UNLOCKED);
            BeckhoffIoSubscribeUpdateVariable(DOOR_LOWER_LOCKED);
            BeckhoffIoSubscribeUpdateVariable(DOOR_LOWER_UNLOCKED);
            BeckhoffIoSubscribeUpdateVariable(CRS_VACUUM);
            BeckhoffIoSubscribeUpdateVariable(CRS_VACUUM_VALUE);
            BeckhoffIoSubscribeUpdateVariable(WH_BLADDER);
            BeckhoffIoSubscribeUpdateVariable(WH_BLADDER_PRESSURE);
            BeckhoffIoSubscribeUpdateVariable(TRANS_BLADDER);
            BeckhoffIoSubscribeUpdateVariable(TRANS_HIGH);
            BeckhoffIoSubscribeUpdateVariable(TRANS_RETRACTED);
            BeckhoffIoSubscribeUpdateVariable(TRANS_PRESSURE);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_BLADDER);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_EXTENDED);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_N2);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_N2_SECOND);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_PRESSURE);
            BeckhoffIoSubscribeUpdateVariable(WAFER_HOLDER_LOCKED);
            BeckhoffIoSubscribeUpdateVariable(BERNOULLI_BLADDER_PRESSURE);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable($"{Module}.{Name}", variable, UpdateVariableValue);
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.{Name}.DoorLockOn",(cmd,args)=> { return DoorLockOnAction(); });
            OP.Subscribe($"{Module}.{Name}.DoorLockOff",(cmd,args)=> { return DoorLockOffAction(); });
            OP.Subscribe($"{Module}.{Name}.VacuumOn", VacuumOnAction);
            OP.Subscribe($"{Module}.{Name}.VacuumOff", VacuumOffAction);
            OP.Subscribe($"{Module}.{Name}.WhBladderOn", WhBladderOnAction);
            OP.Subscribe($"{Module}.{Name}.WhBladderOff", WhBladderOffAction);
            OP.Subscribe($"{Module}.{Name}.BernoulliBladderOn", BernoulliBladderOnAction);
            OP.Subscribe($"{Module}.{Name}.BernoulliBladderOff", BernoulliBladderOffAction);
            OP.Subscribe($"{Module}.{Name}.BernoulliN2On", BernoulliN2OnAction);
            OP.Subscribe($"{Module}.{Name}.BernoulliN2Off", BernoulliN2OffAction);
            OP.Subscribe($"{Module}.{Name}.Load", LoadAction);
            OP.Subscribe($"{Module}.{Name}.Unload", UnloadAction);
            OP.Subscribe($"{Module}.{Name}.InstallCRS", InstallCRSAction);
            OP.Subscribe($"{Module}.{Name}.StartCycle", StartCycleAction);
            OP.Subscribe($"{Module}.{Name}.StopCycle", StopCycleAction);
        }
        #region Operation
        /// 
        /// Door Lock On操作
        /// 
        public bool DoorLockOnAction()
        {
            if (!JudgeRunningState(LoaderSideOperation.DoorOn))
            {
                _currentOperation = LoaderSideOperation.DoorOn;
                _status = _doorlockRoutine.Start(true);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Door Lock Off操作
        /// 
        public bool DoorLockOffAction()
        {
            if (!JudgeRunningState(LoaderSideOperation.DoorOff))
            {
                _currentOperation = LoaderSideOperation.DoorOff;
                _status = _doorlockRoutine.Start(false);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Vacuum On 操作
        /// 
        private bool VacuumOnAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.VacuumOn))
            {
                _currentOperation = LoaderSideOperation.VacuumOn;
                _status = _vacuumRoutine.Start(true);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Vacuum On 操作
        /// 
        private bool VacuumOffAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.VacuumOff))
            {
                _currentOperation = LoaderSideOperation.VacuumOff;
                _status = _vacuumRoutine.Start(false);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// WH Bladder On 操作
        /// 
        private bool WhBladderOnAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.WhBladderOn))
            {
                _currentOperation = LoaderSideOperation.WhBladderOn;
                _status = _whBladderRoutine.Start(true);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// WH Bladder Off 操作
        /// 
        private bool WhBladderOffAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.WhBladderOff))
            {
                _currentOperation = LoaderSideOperation.WhBladderOff;
                _status = _whBladderRoutine.Start(false);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Bernoulli Bladder On 操作
        /// 
        private bool BernoulliBladderOnAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.BernoulliBladderOn))
            {
                _currentOperation = LoaderSideOperation.BernoulliBladderOn;
                _status = _bernoulliBladderRoutine.Start(true);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Bernoulli Bladder Off 操作
        /// 
        private bool BernoulliBladderOffAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.BernoulliBladderOff))
            {
                _currentOperation = LoaderSideOperation.BernoulliBladderOff;
                _status = _bernoulliBladderRoutine.Start(false);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Bernoulli N2 On 操作
        /// 
        public bool BernoulliN2OnAction(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{Name}.{BERNOULLI_N2}");
            bool result = IOModuleManager.Instance.WriteIoValue(ioName, true);            
            return result;
        }
        /// 
        /// Bernoulli N2 Off 操作
        /// 
        public bool BernoulliN2OffAction(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{Name}.{BERNOULLI_N2}");
            bool result = IOModuleManager.Instance.WriteIoValue(ioName, false);            
            return result;
        }
        /// 
        /// Load 操作
        /// 
        public bool LoadAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.Load))
            {
                _currentOperation = LoaderSideOperation.Load;
                _status = _loadRoutine.Start();
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Unload 操作
        /// 
        public bool UnloadAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.Unload))
            {
                _currentOperation = LoaderSideOperation.Unload;
                _status = _unloadRoutine.Start();
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Install CRS 操作
        /// 
        private bool InstallCRSAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.InstallCRS))
            {
                _currentOperation = LoaderSideOperation.InstallCRS;
                _status = _installCRSRoutine.Start();
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// StartCycle 操作
        /// 
        private bool StartCycleAction(string cmd, object[] args)
        {
            if (!JudgeRunningState(LoaderSideOperation.StartCycle))
            {
                _currentOperation = LoaderSideOperation.StartCycle;
                _status = _cycleRoutine.Start(args);
                bool result= _status == RState.Running ;
                if(result)
                {
                    _currentCycle = _cycleRoutine.CurrentCycle.ToString();
                }
                else
                {
                    _currentCycle = "";
                }
                return result;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// StopCycle 操作
        /// 
        private bool StopCycleAction(string cmd, object[] args)
        {
            if (_currentOperation==LoaderSideOperation.StartCycle)
            {
                AbortRoutine();
                return true;
            }
            else
            {
                return true;
            }
        }
        /// 
        /// 判定运行状态
        /// 
        /// 
        private bool JudgeRunningState(LoaderSideOperation operation)
        {
            if (_status == RState.Running)
            {
                EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_LOADER, $"{Module}.{Name} current execute {_currentOperation},cannot {operation}");
                return true;
            }
            return false;
        }
        #endregion
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            PropertyInfo property = SideData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(SideData, value);
            }
        }
        /// 
        /// 定时器
        /// 
        /// 
        public bool OnTimer()
        {
            if (_status == RState.Running)
            {
                if (_currentOperation != LoaderSideOperation.None)
                {
                    IRoutine routine = GetCurrentRoutine(_currentOperation);
                    if (routine != null)
                    {
                        CheckRoutineState(routine, _currentOperation);
                    }
                    else
                    {
                        EndOperation(RState.End);
                    }
                    if(_currentOperation==LoaderSideOperation.StartCycle)
                    {
                        _currentCycle = _cycleRoutine.CurrentCycle.ToString();
                    }
                }
            }
            return true;
        }
        /// 
        /// 获取当前操作对应的Routine
        /// 
        /// 
        /// 
        private IRoutine GetCurrentRoutine(LoaderSideOperation currentOperation)
        {
            switch (currentOperation)
            {
                case LoaderSideOperation.DoorOn:
                case LoaderSideOperation.DoorOff:
                    return _doorlockRoutine;
                case LoaderSideOperation.VacuumOn:
                case LoaderSideOperation.VacuumOff:
                    return _vacuumRoutine;
                case LoaderSideOperation.WhBladderOn:
                case LoaderSideOperation.WhBladderOff:
                    return _whBladderRoutine;
                case LoaderSideOperation.BernoulliBladderOn:
                case LoaderSideOperation.BernoulliBladderOff:
                    return _bernoulliBladderRoutine;
                case LoaderSideOperation.Load:
                    return _loadRoutine;
                case LoaderSideOperation.Unload:
                    return _unloadRoutine;
                case LoaderSideOperation.InstallCRS:
                    return _installCRSRoutine;
                case LoaderSideOperation.StartCycle:
                    return _cycleRoutine;
                default:
                    return null;
            }
        }
        /// 
        /// 检验Routine状态
        /// 
        /// 
        /// 
        private void CheckRoutineState(IRoutine routine, LoaderSideOperation currentOperation)
        {
            RState state = routine.Monitor();
            if (state == RState.End)
            {
                EndOperation(RState.End);
            }
            else if (state == RState.Failed || state == RState.Timeout)
            {
                LOG.WriteLog(eEvent.ERR_LOADER, $"{Module}.{Name}", $"{currentOperation} error");
                EndOperation(RState.Failed);
            }
        }
        /// 
        /// 结束操作
        /// 
        private void EndOperation(RState state)
        {
            _status = state;
            _currentOperation = LoaderSideOperation.None;
        }
        /// 
        /// 中止Routine
        /// 
        public void AbortRoutine()
        {
            IRoutine routine = GetCurrentRoutine(_currentOperation);
            if(routine!=null)
            {
                routine.Abort();
                _currentOperation=LoaderSideOperation.None;
                _status = RState.End;
                _currentCycle = "";
            }
        }
        #region 设备接口
        /// 
        /// 监控
        /// 
        public void Monitor()
        {
            
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
            AbortRoutine();
        }
        #endregion
    }
}