using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.Util;
using MECF.Framework.Common.CommonData.PowerSupplier;
using MECF.Framework.Common.Device.PowerSupplier;
using MECF.Framework.Common.Equipment;
using CyberX8_Core;
using CyberX8_RT.Modules.Transporter;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows;
namespace CyberX8_RT.Devices.PowerSupplier
{
    public class CellPowerSupplier : BaseDevice, IDevice
    {
        private enum PowerSupplierOperation
        {
            None=0,
            StepOperation=1,
            SetCurrent=2,
            SetStartOperation=3
        }
        #region 常量 
        private const string POWERSUPPLIER_DATA = "PowerSupplierData";
        private const string SET_POINT = "SetPoint";
        private const string CURRENT = "Current";
        private const string VOLTAGE = "Voltage";
        private const string ENABLED = "Enabled";
        private const string CONNECTED = "Connected";
        private const string POWER_STATUS = "PowerStatus";
        private const string POWER_CONTROL = "PowerControl";
        private const string POWER_RUN_MODEL = "PowerRunModel";
        #endregion
        #region 内部变量
        /// 
        /// 数据
        /// 
        private PowerSupplierData _powerSupplierData;
        /// 
        /// 通道
        /// 
        private byte _channel=0;
        /// 
        /// 设备参数
        /// 
        private PowerSupplierDevice _deviceParameter;
        /// 
        /// 定时器
        /// 
        private PeriodicJob _periodicJob;
        /// 
        /// 指定读取指令集合
        /// 
        private ConcurrentQueue _readCommandList = new ConcurrentQueue();
        /// 
        /// 步阶Routine
        /// 
        private PowerSupplierStepRoutine _powerSupplierStepRoutine;
        /// 
        /// 设置电流Routine
        /// 
        private PowerSupplierSetCurrentRoutine _powerSupplierSetCurrentRoutine;
        /// 
        /// 设置步阶Routine
        /// 
        private PowerSupplierStartStepRoutine _powerSupplierStartStepRoutine;
        /// 
        /// 状态
        /// 
        private RState _status;
        /// 
        /// 当前操作
        /// 
        private PowerSupplierOperation _currentOperation;
        /// 
        /// 
        /// 读取电流时间
        /// 
        private DateTime _sendDateTime = DateTime.Now;
        /// 
        /// 连接上升沿
        /// 
        private R_TRIG _connectedTrig = new R_TRIG();
        /// 
        /// 发送Remote上升沿
        /// 
        private R_TRIG _sendRemoteTrig = new R_TRIG();
        /// 
        /// 连接成功时间
        /// 
        private DateTime _connectTime = DateTime.Now;
        /// 
        /// 读取电流数值比例
        /// 
        private int _unitScale = 10000;
        /// 
        /// 读取电压数值比例
        /// 
        private int _voltageUnitScale = 10000;
        /// 
        /// 设置数值比例
        /// 
        private int _unitSetScale = 1000;
        /// 
        /// 设置电压数值比例
        /// 
        private int _voltageUnitSetScale = 1000;
        #endregion
        #region 属性
        /// 
        /// 数据
        /// 
        public PowerSupplierData PowerSupplierData { get { return _powerSupplierData; } }
        /// 
        /// 状态
        /// 
        public RState Status { get { return _status; } }
        /// 
        /// 连接状态
        /// 
        public bool IsConnected { get { return PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public CellPowerSupplier(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
        {
            _powerSupplierData = new PowerSupplierData();
            _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            InitializeOperation();
            InitializeData();
            InitializeRoutine();
            return true;
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.Enable", EnableOperation);
            OP.Subscribe($"{Module}.Disable", DisableOperation);
            OP.Subscribe($"{Module}.SetPoint", SetPointOperation);
            OP.Subscribe($"{Module}.StartStepPeriod", StartStepPeriod);
            OP.Subscribe($"{Module}.SetLocalControl", SetLocalOperation);
            OP.Subscribe($"{Module}.SetRemoteControl", SetRemoteOperation);
            OP.Subscribe($"{Module}.Abort", AbortOperation);
        }
        /// 
        /// 初始化数据
        /// 
        private void InitializeData()
        {
            _deviceParameter = PowerSupplierDeviceConfigManager.Instance.GetPowerSupplierDeviceByName(Module);
            if(_deviceParameter!=null)
            {
                if(!byte.TryParse(_deviceParameter.Address,out _channel))
                {
                    LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"{Module} channel is invalid");
                }
                _unitScale = _deviceParameter.UnitScale;
                _unitSetScale= _deviceParameter.UnitSetScale;
                _voltageUnitSetScale = _deviceParameter.VoltageUnitSetScale;
                _voltageUnitScale = _deviceParameter.VoltageUnitScale;
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"{Module} is not in config xml");
            }
            DATA.Subscribe($"{Module}.{POWERSUPPLIER_DATA}", () => _powerSupplierData, Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{CONNECTED}", () => PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, ENABLED, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, SET_POINT, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, VOLTAGE, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, CURRENT, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, POWER_STATUS, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module,POWER_CONTROL, UpdateVariableValue);
            PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, POWER_RUN_MODEL, UpdateVariableValue);
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _powerSupplierStepRoutine = new PowerSupplierStepRoutine(Module);
            _powerSupplierSetCurrentRoutine = new PowerSupplierSetCurrentRoutine(Module);
            _powerSupplierStartStepRoutine= new PowerSupplierStartStepRoutine(Module);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            PropertyInfo property = PowerSupplierData.GetType().GetProperty(variable);
            
            if (property != null)
            {
                if (!PowerSupplierData.IsDataInitialized)
                {
                    PowerSupplierData.IsDataInitialized = true;
                    SetPowerCCStatus();
                }
                if(variable==SET_POINT)
                {
                    if (double.TryParse(value.ToString(), out double doubleValue))
                    {
                        property.SetValue(PowerSupplierData, doubleValue / _unitSetScale);
                    }
                    else
                    {
                        property.SetValue(PowerSupplierData, value);
                    }
                }
                else if(variable==CURRENT)
                {
                    if (double.TryParse(value.ToString(), out double doubleValue))
                    {
                        property.SetValue(PowerSupplierData, doubleValue / _unitScale);
                    }
                    else
                    {
                        property.SetValue(PowerSupplierData, value);
                    }
                }
                else if (variable == VOLTAGE)
                {
                    if (double.TryParse(value.ToString(), out double doubleValue))
                    {
                        property.SetValue(PowerSupplierData, doubleValue / _voltageUnitScale);
                    }
                    else
                    {
                        property.SetValue(PowerSupplierData, value);
                    }
                }
                else
                {
                    property.SetValue(PowerSupplierData, value);
                }
            }
        }
        /// 
        /// 定时器
        /// 
        /// 
        private bool OnTimer()
        {
            bool connected = PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module);
            _connectedTrig.CLK = connected;
            if (_connectedTrig.Q)
            {
                _connectTime = DateTime.Now;
                return true;
            }
            if(!connected)
            {
                _connectedTrig.RST = true;
                PowerSupplierDeviceConfigManager.Instance.StartConnectDevice(Module);
                return true;
            }
            if (!_sendRemoteTrig.Q)
            {
                if (DateTime.Now.Subtract(_connectTime).TotalSeconds >= 1)
                {
                    _sendRemoteTrig.CLK = SetRemoteOperation("", null);
                    SetRemoteOperation("", null);
                }
                return true;
            }
            if (_readCommandList.Count != 0)
            {
                if (_readCommandList.TryDequeue(out string command))
                {
                    switch (command)
                    {
                        case ENABLED:
                            PowerSupplierDeviceConfigManager.Instance.GetChannelOutputSwitch(Module, _channel);
                            break;
                        case SET_POINT:
                            PowerSupplierDeviceConfigManager.Instance.GetChannelCurrentSetting(Module, _channel);
                            break;
                        case POWER_STATUS:
                            PowerSupplierDeviceConfigManager.Instance.GetChannelPowerStatus(Module, _channel);
                            break;
                        case POWER_CONTROL:
                            PowerSupplierDeviceConfigManager.Instance.GetChannelPowerControl(Module, _channel);
                            break;
                        case POWER_RUN_MODEL:
                            PowerSupplierDeviceConfigManager.Instance.GetPowerRunmodelControl(Module, _channel);
                            break;
                    }
                    _sendDateTime = DateTime.Now;
                }
            }
            else
            {
                //控制模式为local
                if (PowerSupplierData.PowerControlContent != null && PowerSupplierData.PowerControlContent.ToLower() == "local")
                {
                    return true;
                }
                if (DateTime.Now.Subtract(_sendDateTime).TotalMilliseconds >= 300)
                {
                    ReadCurrentAndVoltage();
                }
            }
            if(_status==RState.Running)
            {
                IRoutine routine = GetCurrentRoutine();
                if (routine != null)
                {
                    _status = routine.Monitor();
                    if (_status == RState.Failed || _status == RState.Timeout)
                    {
                        _status = RState.Failed;
                        if(_currentOperation==PowerSupplierOperation.SetCurrent)
                        {
                            DisableOperation("", null);
                        }
                        _currentOperation = PowerSupplierOperation.None;
                    }
                    else if (_status == RState.End)
                    {
                        _currentOperation = PowerSupplierOperation.None;
                    }
                }
            }
            return true;
        }
        /// 
        /// 读取电流和电压
        /// 
        private void ReadCurrentAndVoltage()
        {
            _sendDateTime = DateTime.Now;
            PowerSupplierDeviceConfigManager.Instance.GetChannelCurrentAndVoltage(Module, _channel);
        }
        #region Operation
        /// 
        /// Enable Operation
        /// 
        /// 
        /// 
        /// 
        public bool EnableOperation(string cmd, object[] args)
        {
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            if (PowerSupplierData.SetPoint==0)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Setpoint is 0,cannot enable output");
                return false;
            }
            EnableOutput();
            LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control enable output Success");
            return true;
        }
        /// 
        /// Disable Operation
        /// 
        /// 
        /// 
        /// 
        public bool DisableOperation(string cmd, object[] args)
        {
            if(_status==RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            
            DisableOutput();
            LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control disable output Success");
            return true;
        }
        /// 
        /// 中止
        /// 
        /// 
        /// 
        /// 
        private bool AbortOperation(string cmd, object[] args)
        {
            if(_status==RState.Running)
            {
                IRoutine routine = GetCurrentRoutine();
                if(routine!=null)
                {
                    routine.Abort();
                }
                DisableOutput();
                PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module, _channel, (byte)PowerRunModelEnum.Normal);
                LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"abort {_currentOperation} operation");
                _status = RState.End;
                _currentOperation = PowerSupplierOperation.None;
                _readCommandList.Enqueue(POWER_RUN_MODEL);
            }
            return true;
        }
        /// 
        /// 关闭输出
        /// 
        /// 
        public bool DisableOutput()
        {
            if(PowerSupplierData==null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if(PowerSupplierData.PowerControl==(short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelOutputSwitchControl(Module, _channel, false);
            _sendDateTime = DateTime.Now;
            _readCommandList.Enqueue(ENABLED);
            _readCommandList.Enqueue(POWER_STATUS);
            return result;
        }
        /// 
        /// 启动输出
        /// 
        /// 
        public bool EnableOutput()
        {
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelOutputSwitchControl(Module, _channel, true);
            _sendDateTime = DateTime.Now;
            _readCommandList.Enqueue(ENABLED);
            _readCommandList.Enqueue(POWER_STATUS);
            return result;
        }
        /// 
        /// SetPoint
        /// 
        /// 
        /// 
        /// 
        public bool SetPointOperation(string cmd, object[] args)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            if (args.Length<2)
            {
                return false;
            }
            if (double.TryParse(args[1].ToString(), out double value))
            {
                SetCurrent(value);
            }
            return true;
        }
        /// 
        /// 设置电流
        /// 
        /// 
        /// 
        public bool SetCurrent(double current)
        {
            PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module, _channel, (byte)PowerRunModelEnum.Normal);
            int setPoint = (int)Math.Round(_unitSetScale * current, 0);
            bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelCurrent(Module, _channel, setPoint);
            _sendDateTime = DateTime.Now;
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Current {current} Setting success");
                _readCommandList.Enqueue(SET_POINT);
                _readCommandList.Enqueue(POWER_RUN_MODEL);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        /// 
        private bool StartStepPeriod(string cmd, object[] args)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            bool result= _powerSupplierStepRoutine.Start(args)==RState.Running;
            if(result)
            {
                _status = RState.Running;
                _currentOperation = PowerSupplierOperation.StepOperation;
            }
            return result;
        }
        /// 
        /// 启动设置步阶,
        /// 
        /// 
        /// 
        /// 
        public bool StartSetStepPeriodNoWaitEnd(List datas)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            bool result = _powerSupplierStartStepRoutine.Start(datas) == RState.Running;
            if (result)
            {
                _status = RState.Running;
                _currentOperation = PowerSupplierOperation.SetStartOperation;
            }
            return result;
        }
        /// 
        /// 设置步阶
        /// 
        /// 
        /// 
        /// 
        public bool SetStepPeriod(string cmd, object[] args)
        {
            List powerSupplierStepPeriodDatas = (List)args[1];
            bool result=PowerSupplierDeviceConfigManager.Instance.SetStepPeriod(Module, _channel, powerSupplierStepPeriodDatas,_unitSetScale, _voltageUnitSetScale);
            _sendDateTime = DateTime.Now;
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Step Period Set Success");
                return true;
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"Step Period Set Fail");
                return false;
            }
        }
        /// 
        /// 启动步阶
        /// 
        /// 
        /// 
        /// 
        public bool StartStepPeriod(ushort endStep,ushort cycle)
        {
            bool result = PowerSupplierDeviceConfigManager.Instance.StartStepPeriod(Module, _channel, 1, endStep, cycle);
            _sendDateTime= DateTime.Now;
            return result;
        }
        /// 
        /// 设置电源运行模式
        /// 
        /// 
        /// 
        public bool SwitchPowerRunModel(byte runModel)
        {
            bool result= PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module,_channel, runModel);
            _sendDateTime = DateTime.Now;
            _readCommandList.Enqueue(POWER_RUN_MODEL);
            return result;
        }
        /// 
        /// 设置本地模式 
        /// 
        /// 
        /// 
        /// 
        private bool SetLocalOperation(string cmd, object[] args)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelPowerControl(Module, _channel, 1);
            _sendDateTime = DateTime.Now;
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control Switch Local Control Success");
                _readCommandList.Enqueue(POWER_CONTROL);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 设置远程模式
        /// 
        /// 
        /// 
        /// 
        private bool SetRemoteOperation(string cmd, object[] args)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelPowerControl(Module, _channel, 2);
            _sendDateTime = DateTime.Now;
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control Switch Remote Control Success");
                _readCommandList.Enqueue(POWER_CONTROL);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 设置电流并设置输出
        /// 
        /// 
        /// 
        /// 
        public bool SetCurrentAndOutput(double current)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy");
                return false;
            }
            if (PowerSupplierData == null)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null");
                return false;
            }
            if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local)
            {
                LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control");
                return false;
            }
            bool result = _powerSupplierSetCurrentRoutine.Start(current) == RState.Running;
            if (result)
            {
                _status = RState.Running;
                _currentOperation = PowerSupplierOperation.SetCurrent;
            }
            return result;
        }
        /// 
        /// 获取当前的routine
        /// 
        /// 
        private IRoutine GetCurrentRoutine()
        {
            switch(_currentOperation)
            {
                case PowerSupplierOperation.StepOperation:
                    return _powerSupplierStepRoutine;
                case PowerSupplierOperation.SetCurrent:
                    return _powerSupplierSetCurrentRoutine;
                case PowerSupplierOperation.SetStartOperation:
                    return _powerSupplierStartStepRoutine;
                default:
                    return null;
            }
        }
        /// 
        /// 设置CC电源状态
        /// 
        private void SetPowerCCStatus()
        {
            _readCommandList.Enqueue(POWER_STATUS);
            _readCommandList.Enqueue(SET_POINT);
            _readCommandList.Enqueue(ENABLED);
            _readCommandList.Enqueue(POWER_CONTROL);
            _readCommandList.Enqueue(POWER_RUN_MODEL);
        }
        #endregion
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
            DisableOutput();
        }
    }
}