using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using Aitex.Core.Util;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.PUF
{
    public class PufVacuum : BaseDevice, IDevice
    {
        #region 常量
        private const string CHUCKA_VAC = "ChuckAVac";
        private const string CHUCKB_VAC = "ChuckBVac";
        private const string CHUCKA_RELEASE = "ChuckARelease";
        private const string CHUCKB_RELEASE = "ChuckBRelease";
        private const string CHUCKA_VACUUM_STATUS = "ChuckAVacuumStatus";
        private const string CHUCKB_VACUUM_STATUS = "ChuckBVacuumStaus";
        private const string CHUCKA = "ChuckA";
        private const string CHUCKB = "ChuckB";
        private const string VACUUM_LEAK = "VacuumLeak";
        #endregion
        #region 内部变量
        private bool _chuckAWaferPresent;
        private bool _chuckBWaferPresent;
        private bool _chuckAReleased;
        private bool _chuckBReleased;
        private double _chuckAValue;
        private double _chuckBValue;
        private double _chuckVacuumCloseLimit;
        private double _chuckVacuumOpenLimit;
        private double _chuckVacuumWaferAbsent;
        private double _chuckVacuumWaferPresent;
        private string _chuckAVacuumStatus = "";
        private string _chuckBVacuumStatus = "";
        private DateTime _leakADateTime = DateTime.Now;
        private System.Timers.Timer _leakATimer;
        private DateTime _leakBDateTime = DateTime.Now;
        private System.Timers.Timer _leakBTimer;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 首次加载数据成功
        /// 
        private bool _firstLoad = false;
        #endregion
        #region 属性
        /// 
        /// ChuckA Wafer Present状态
        /// 
        public bool ChuckAWaferPresent
        {
            get { return _chuckAWaferPresent; }
            set { _chuckAWaferPresent = value; }
        }
        /// 
        /// ChuckB Wafer Present
        /// 
        public bool ChuckBWaferPresent
        {
            get { return _chuckBWaferPresent; }
            set { _chuckBWaferPresent = value; }
        }
        /// 
        /// Side A Vacuum状态
        /// 
        public string ChuckAVacuumStatus
        {
            get { return _chuckAVacuumStatus; }
        }
        /// 
        /// Side B Vacuum状态
        /// 
        public string ChuckBVacuumStatus
        {
            get { return _chuckBVacuumStatus; }
        }
        /// 
        /// Side B 是否关闭真空
        /// 
        public bool ISChuckBReleased
        {
            get { return _chuckBReleased; }
        }
        /// 
        /// Side A是否关闭真空
        /// 
        public bool IsChuckAReleased
        {
            get { return _chuckAReleased; }
        }
        /// 
        /// 所有io变量是否初始化
        /// 
        public bool IOInitialized { get { return AllIoVariableInitialized(); } }
        #endregion
        #region 事件
        public event EventHandler OnVacuumLeak;
        public event EventHandler OnVacuumResume;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public PufVacuum(string moduleName):base(moduleName,"Vacuum","Vacuum","Vacuum")
        {
            LoadConfigParameter();
            _leakATimer = new System.Timers.Timer(500);
            _leakATimer.Elapsed += LeakATimer_Elapsed;
            _leakBTimer=new System.Timers.Timer(500);
            _leakBTimer.Elapsed += LeakBTimer_Elapsed;
        }
        /// 
        /// 加载配置参数
        /// 
        private void LoadConfigParameter()
        {
            _chuckVacuumCloseLimit = SC.GetValue($"{Module}.ChuckVacuumCloseLimit");
            _chuckVacuumOpenLimit = SC.GetValue($"{Module}.ChuckVacuumOpenLimit");
            _chuckVacuumWaferAbsent = SC.GetValue($"{Module}.ChuckVacuumWaferAbsent");
            _chuckVacuumWaferPresent = SC.GetValue($"{Module}.ChuckVacuumWaferPresent");
        }
        /// 
        /// Leak定时器
        /// 
        /// 
        /// 
        /// 
        private void LeakATimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if(DateTime.Now.Subtract(_leakADateTime).TotalSeconds>=2)
            {
                _chuckAVacuumStatus = VACUUM_LEAK;
                LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckA vacuum leak");
                if (OnVacuumLeak != null)
                {
                    OnVacuumLeak(this, Module);
                }
                _leakATimer.Stop();
            }
        }
        /// 
        /// LeakB定时器
        /// 
        /// 
        /// 
        /// 
        private void LeakBTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (DateTime.Now.Subtract(_leakBDateTime).TotalSeconds >= 2)
            {
                _chuckBVacuumStatus = VACUUM_LEAK;
                LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckB vacuum leak");
                if (OnVacuumLeak != null)
                {
                    OnVacuumLeak(this, Module);
                }
                _leakBTimer.Stop();
            }
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            SubscribeData();
            InitializeOperation();
            SubscribeValueAction();
            return true;
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumAOn}", VaccumAOnOperation);
            OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumBOn}", VaccumBOnOperation);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(CHUCKA_VAC);
            BeckhoffIoSubscribeUpdateVariable(CHUCKB_VAC);
            BeckhoffIoSubscribeUpdateVariable(CHUCKA_RELEASE);
            BeckhoffIoSubscribeUpdateVariable(CHUCKB_RELEASE);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue);
        }
        /// 
        /// 是否所有IO变量初始化完成
        /// 
        /// 
        private bool AllIoVariableInitialized()
        {
            foreach (string item in _variableInitializeDic.Keys)
            {
                if (!_variableInitializeDic[item])
                {
                    LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized");
                    return false;
                }
            }
            return true;
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            DATA.Subscribe($"{Module}.{CHUCKA_RELEASE}", () => _chuckAReleased,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CHUCKB_RELEASE}", () => _chuckBReleased, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CHUCKA_VAC}", () => _chuckAValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CHUCKB_VAC}", () => _chuckBValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CHUCKA_VACUUM_STATUS}", () => _chuckAVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CHUCKB_VACUUM_STATUS}", () => _chuckBVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if(!_firstLoad)
            {
                _firstLoad = true;
                VacuumAOn();
                VacuumBOn();
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
            if (variable == $"{CHUCKA_RELEASE}")
            {
                _chuckAReleased = (bool)value;
                var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
                _chuckAWaferPresent = item.Item1;
                _chuckAVacuumStatus = item.Item2;
                if (_chuckAVacuumStatus != VACUUM_LEAK && item.Item2 ==  VACUUM_LEAK)
                {
                    _leakADateTime = DateTime.Now;
                    _leakATimer.Start();
                }
                else if (item.Item2 != VACUUM_LEAK)
                {
                    _leakBTimer.Stop();
                }
            }
            else if(variable==$"{CHUCKB_RELEASE}")
            {
                _chuckBReleased=(bool)value;
                var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
                if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
                {
                    _leakBDateTime = DateTime.Now;
                    _leakBTimer.Start();
                }
                else if (item.Item2 != VACUUM_LEAK)
                {
                    _leakBTimer.Stop();
                }
                _chuckBWaferPresent = item.Item1;
                _chuckBVacuumStatus = item.Item2;
            }
            else if(variable==$"{CHUCKA_VAC}")
            {
                _chuckAValue = (double)value;
                var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
                if(_chuckAVacuumStatus!= VACUUM_LEAK&&item.Item2== VACUUM_LEAK)
                {
                    _leakADateTime = DateTime.Now;
                    _leakATimer.Start();
                }
                else if (item.Item2 != VACUUM_LEAK)
                {
                    _leakATimer.Stop();
                }
                _chuckAWaferPresent =item.Item1;
                _chuckAVacuumStatus=item.Item2;
            }
            else if(variable==$"{CHUCKB_VAC}")
            {
                _chuckBValue=(double)value;
                var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
                if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
                {
                    _leakBDateTime = DateTime.Now;
                    _leakBTimer.Start();
                }
                else if(item.Item2!=VACUUM_LEAK)
                {
                    _leakBTimer.Stop();
                }
                _chuckBWaferPresent = item.Item1;
                _chuckBVacuumStatus = item.Item2;
            }
        }
        /// 
        /// 判定Wafer Present
        /// 
        /// 
        /// 
        /// 
        private (bool,string) JudgeWaferPresent(double chuckValue,bool chuckRelease,string chuck)
        {
            LoadConfigParameter();
            if (!chuckRelease)
            {
                if(chuckValue < _chuckVacuumWaferPresent)
                {
                    ResumeVacuum();
                    return (true,"WaferPresent");
                }
                else if( chuckValue > _chuckVacuumWaferAbsent)
                {
                    ResumeVacuum();
                    return (false,"WaferAbsent");
                }
                else
                {
                    return (false,"InvalidData");
                }
            }
            else
            {
                if(chuckValue<=_chuckVacuumCloseLimit)
                {
                    return (false,"VacuumLeak");
                }
                else if(chuckValue<=_chuckVacuumOpenLimit)
                {
                    ResumeVacuum();
                    return (false, "VacuumOff");
                }
                else
                {
                    ResumeVacuum();
                    return (false, "");
                }
            }
        }
        /// 
        /// 故障恢复
        /// 
        private void ResumeVacuum()
        {
            if (OnVacuumResume != null)
            {
                OnVacuumResume(this, Module);
            }
        }
        /// 
        /// VacuumAOn操作
        /// 
        /// 
        /// 
        /// 
        private bool VaccumAOnOperation(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
            if(!string.IsNullOrEmpty(ioName))
            {
                IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
            }
            return true;
        }
        /// 
        /// VacuumBOn操作
        /// 
        /// 
        /// 
        /// 
        private bool VaccumBOnOperation(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
            if (!string.IsNullOrEmpty(ioName))
            {
                IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
            }
            return true;
        }
        /// 
        /// VacuumA关闭
        /// 
        public bool VacuumAOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
            if (!string.IsNullOrEmpty(ioName))
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, true);
            }
            return false;
        }
        /// 
        /// VacuumB关闭
        /// 
        public bool VacuumBOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
            if (!string.IsNullOrEmpty(ioName))
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, true);
            }
            return false;
        }
        /// 
        /// VacuumA打开
        /// 
        public bool VacuumAOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
            if (!string.IsNullOrEmpty(ioName))
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, false);
            }
            return false;
        }
        /// 
        /// VacuumB打开
        /// 
        public bool VacuumBOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
            if (!string.IsNullOrEmpty(ioName))
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, false);
            }
            return false;
        }
        /// 
        /// 监控
        /// 
        public void Monitor()
        {
        }
        /// 
        /// 重置
        /// 
        public void Reset()
        {
        }
        /// 
        /// 中止
        /// 
        public void Terminate()
        {
        }
    }
}