using Aitex.Common.Util;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Device.TemperatureController;
using MECF.Framework.Simulator.Core.Driver;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MECF.Framework.Simulator.Core.Commons
{
    public class TemperatureControllerSerialPortDevice : BaseSerialSimulator
    {
        #region 常量
        private const string PORT_NAME = "com12";
        private const byte ADD_FLAG = 0x30;
        #endregion
        #region 内部变量
        /// 
        /// 控制字字典
        /// 
        private Dictionary dic = new Dictionary() 
        {
            { 0x05,"ENQ" },
            { 0x02,"STX" },
            { 0x03,"ETX" },
            { 0x06,"ACK" },
            { 0x0D,"CR" },
            { 0x01,"SOH" }
        };
        /// 
        /// 命令字典
        /// 
        private Dictionary comdic = new Dictionary()
        {
            { 0x31,"Target Temp" },
            { 0x32,"Internal" },
            { 0x33,"External" },
            { 0x34,"Alarm" },
            { 0x35,"Average" },
            { 0x36,"offset" },
            { 0x39,"control" },
            { 0x41,"PB" },
            { 0x42,"ARW" },
            { 0x43,"IConstant" },
            { 0x44,"DConstant" },
            { 0x45,"OutPutRatio" },
            { 0x46,"HeatingLimit" },
            { 0x47,"CoolingLimit" },
            { 0x48,"Saved" }
        };
        private double[] _reserviorValues = new double[10];
        private double[] _heatValues = new double[10];
        private double[] _targetValues = new double[10];
        private int _controlOperation = 0;
        //private byte[] alarm = new byte[12] { 0,0,0,0,1,0,0,0,0,0,0,0};
        private byte[] alarm = new byte[3] {0x30,0x33,0x30};
        System.Timers.Timer[] _timers;
        private int _tcCount = 1;
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public TemperatureControllerSerialPortDevice(string port) : base(port, SerialType.BUFFER)
        {
            Init(port);           
        }
        /// 
        /// 初始化
        /// 
        /// 
        private void Init(string port)
        {
            //加载TC配置
            try
            {
                string oldXmlPath = PathManager.GetCfgDir();
                string newXmlPath = oldXmlPath.Replace("CyberX8_Simulator", "CyberX8_RT") + "Devices\\SMCCfg.xml";
                TemperatureConfig cfg = CustomXmlSerializer.Deserialize(new FileInfo(newXmlPath));
                if (cfg != null)
                {
                    foreach (TemperatureDeviceConfig config in cfg.TemperatureDeviceConfigs)
                    {
                        if (int.TryParse(config.Port.Substring(3,2), out int result1) && int.TryParse(port.Substring(3, 2), out int result2))
                        {
                            if(result1 + 1 == result2) _tcCount = config.TemperatureDevices.Count;
                        }
                    }
                }
            }
            catch (Exception ex) 
            {
            }
            //
            _timers = new System.Timers.Timer[_tcCount];
            for(int i = 0; i < _tcCount; i++)
            {
                _heatValues[i] = 16.5;
                _targetValues[i] = 0;
                _reserviorValues[i] = 16.6;
                _timers[i] = new System.Timers.Timer(50);
                switch (i)
                {   
                    case 0:
                        _timers[0].Elapsed += Timer_Elapsed0;
                        break;
                    case 1:
                        _timers[1].Elapsed += Timer_Elapsed1;
                        break;
                    case 2:
                        _timers[2].Elapsed += Timer_Elapsed2;
                        break;
                    case 3:
                        _timers[3].Elapsed += Timer_Elapsed3;
                        break;
                    case 4:
                        _timers[4].Elapsed += Timer_Elapsed4;
                        break;
                    default:
                        break;
                }               
            }                       
        }
        /// 
        /// TC1-1的调温
        /// 
        /// 
        /// 
        private void Timer_Elapsed0(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Math.Abs(_heatValues[0] - _targetValues[0]) >= 0.2)
            {
                //内部调温
                if (_heatValues[0] < _targetValues[0])
                {
                    _heatValues[0] += 0.1;
                }
                else
                {
                    _heatValues[0] -= 0.1;
                }
                //外部调温
                if (_reserviorValues[0] < _targetValues[0])
                {
                    _reserviorValues[0] += 0.1;
                }
                else
                {
                    _reserviorValues[0] -= 0.1;
                }
            }
            else
            {
                _timers[0].Stop();
            }
        }
        /// 
        /// TC1-2的调温
        /// 
        /// 
        /// 
        private void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Math.Abs(_heatValues[1] - _targetValues[1]) >= 0.2)
            {
                //内部调温
                if (_heatValues[1] < _targetValues[1])
                {
                    _heatValues[1] += 0.1;
                }
                else
                {
                    _heatValues[1] -= 0.1;
                }
                //外部调温
                if (_reserviorValues[1] < _targetValues[1])
                {
                    _reserviorValues[1] += 0.1;
                }
                else
                {
                    _reserviorValues[1] -= 0.1;
                }
            }
            else
            {
                _timers[1].Stop();
            }
        }
        /// 
        /// TC1-3的调温
        /// 
        /// 
        /// 
        private void Timer_Elapsed2(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Math.Abs(_heatValues[2] - _targetValues[2]) >= 0.2)
            {
                //内部调温
                if (_heatValues[2] < _targetValues[2])
                {
                    _heatValues[2] += 0.1;
                }
                else
                {
                    _heatValues[2] -= 0.1;
                }
                //外部调温
                if (_reserviorValues[2] < _targetValues[2])
                {
                    _reserviorValues[2] += 0.1;
                }
                else
                {
                    _reserviorValues[2] -= 0.1;
                }
            }
            else
            {
                _timers[2].Stop();
            }
        }
        /// 
        /// TC1-4的调温
        /// 
        /// 
        /// 
        private void Timer_Elapsed3(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Math.Abs(_heatValues[3] - _targetValues[3]) >= 0.2)
            {
                //内部调温
                if (_heatValues[3] < _targetValues[3])
                {
                    _heatValues[3] += 0.1;
                }
                else
                {
                    _heatValues[3] -= 0.1;
                }
                //外部调温
                if (_reserviorValues[3] < _targetValues[3])
                {
                    _reserviorValues[3] += 0.1;
                }
                else
                {
                    _reserviorValues[3] -= 0.1;
                }
            }
            else
            {
                _timers[3].Stop();
            }
        }
        /// 
        /// TC1-5的调温
        /// 
        /// 
        /// 
        private void Timer_Elapsed4(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Math.Abs(_heatValues[4] - _targetValues[4]) >= 0.2)
            {
                //内部调温
                if (_heatValues[4] < _targetValues[4])
                {
                    _heatValues[4] += 0.1;
                }
                else
                {
                    _heatValues[4] -= 0.1;
                }
                //外部调温
                if (_reserviorValues[4] < _targetValues[4])
                {
                    _reserviorValues[4] += 0.1;
                }
                else
                {
                    _reserviorValues[4] -= 0.1;
                }
            }
            else
            {
                _timers[4].Stop();
            }
        }
        protected override string MessageConvert(byte[] byt)
        {
            string str = "";
            for(int i=0;i7)
            {
                byte[] byt = new byte[data.Length - 3];
                Array.Copy(data, 3, byt, 0, byt.Length);
                ProcessNormalCommand(byt);
            }
            else if (data[0] == 0x01)
            {
                ProcessNormalCommand(data);
            }
        }
        private void ProcessNormalCommand(byte[] data)
        {
            if (data[0] == 0x01 && data[data.Length-1]==0x0D)
            {
                if (data.Length == 7)
                {
                    ProcessReadCommand(data);
                }
                else if (data.Length > 7)
                {
                    ProcessSetCommand(data);
                }
            }
        }
        private void ProcessReadCommand(byte[] data)
        {
            switch(data[3])
            {
                case 0x31:
                    ReadTargetValue(data); 
                    break;
                case 0x32:
                    ReadReserviorValue(data);
                    break;
                case 0x33:
                    ReadHeatValue(data); 
                    break;
                case 0x34:
                    ReadAlarmValue(data);
                    break;
                case 0x39:
                    ReadControlOperationValue(data);
                    break;
            }
        }
        private void ProcessSetCommand(byte[] data)
        {
            switch(data[3])
            {
                case 0x31:
                    _targetValues[data[1] - ADD_FLAG - 1] = (data[4] - ADD_FLAG) * 10 + (data[5] - ADD_FLAG) + (data[6]-ADD_FLAG)*0.1;
                    _timers[data[1] - ADD_FLAG -1].Start();
                    break;
                case 0x39:
                    _controlOperation = data[7] - ADD_FLAG;
                    if(_controlOperation == 0)
                    {
                        //停止调温
                        _timers[data[1] - ADD_FLAG - 1].Stop();
                    }
                    else
                    {
                        //继续调温
                        _timers[data[1] - ADD_FLAG - 1].Start();
                    }
                    break;
            }
            WriteConfirmData(data[1]);
        }
        /// 
        /// 回复确认
        /// 
        /// 
        private void WriteConfirmData(byte id)
        {
            byte[] confirm = new byte[3];
            confirm[0] = 0x06;
            confirm[1] = id;
            confirm[2] = 0x0d;
            WriteBuffer(confirm);
        }
        private void ReadTargetValue(byte[] data)
        {
            byte[] byt = new byte[12];
            byt[0] = data[0];
            byt[1] = data[1];
            byt[2] = 0x02;
            byt[3] = data[3];
            byte[] decadeByte = GetDecadeBytes(_targetValues[data[1] - ADD_FLAG - 1]);
            Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
            byt[5 + decadeByte.Length] = 0;
            byt[6 + decadeByte.Length] = 0;
            byt[11] = 0x0D;
            WriteBuffer(byt);
        }
        private void ReadReserviorValue(byte[] data)
        { 
            byte[] byt = new byte[12];
            byt[0] = data[0];
            byt[1] = data[1];
            byt[2] = 0x02;
            byt[3] = data[3];
            byte[] decadeByte = GetDecadeBytes(_reserviorValues[data[1] - ADD_FLAG - 1]);
            Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
            byt[5 + decadeByte.Length] = 0;
            byt[6 + decadeByte.Length] = 0;
            byt[11] = 0x0D;
            WriteBuffer(byt);
        }
        private void ReadHeatValue(byte[] data)
        {
            byte[] byt = new byte[12];
            byt[0] = data[0];
            byt[1] = data[1];
            byt[2] = 0x02;
            byt[3] = data[3];
            byte[] decadeByte = GetDecadeBytes(_heatValues[data[1] - ADD_FLAG - 1]);
            Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
            byt[5 + decadeByte.Length] = 0;
            byt[6 + decadeByte.Length] = 0;
            byt[11] = 0x0D;
            WriteBuffer(byt);
        }
        private void ReadControlOperationValue(byte[] data)
        {
            byte[] byt = new byte[12];
            byt[0] = data[0];
            byt[1] = data[1];
            byt[2] = 0x02;
            byt[3] = data[3];
            byte[] decadeByte = GetKilloBytes(_controlOperation);
            Array.Copy(decadeByte, 0, byt, 4, decadeByte.Length);
            byt[5 + decadeByte.Length] = 0;
            byt[6 + decadeByte.Length] = 0;
            byt[11] = 0x0D;
            WriteBuffer(byt);
        }
        private void ReadAlarmValue(byte[] data)
        {
            byte[] byt = new byte[8+alarm.Length];
            byt[0] = data[0];
            byt[1] = data[1];
            byt[2] = 0x02;
            byt[3] = data[3];
            Array.Copy(alarm, 0, byt, 4, alarm.Length);
            byt[5 + alarm.Length] = 0;
            byt[6 + alarm.Length] = 0;
            byt[7+alarm.Length] = 0x0D;
            WriteBuffer(byt);
        }
        /// 
        /// 获取温度数组(10|1|0.1|0.01)
        /// 
        /// 
        /// 
        private byte[] GetDecadeBytes(double temperature)
        {
            byte decade = GetSendByteData((byte)Math.Floor(temperature / 10));
            byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
            byte digital = GetSendByteData((byte)Math.Floor(temperature * 10 % 10));
            return new byte[4] { decade, unit, digital, ADD_FLAG };
        }
        /// 
        /// 获取千级数组(1000|100|10|1)
        /// 
        /// 
        /// 
        private byte[] GetKilloBytes(double temperature)
        {
            byte kilo = GetSendByteData((byte)Math.Floor(temperature / 1000));
            byte hundred = GetSendByteData((byte)Math.Floor(temperature % 1000/100));
            byte decade = GetSendByteData((byte)Math.Floor(temperature % 100 / 10));
            byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
            return new byte[4] { kilo, hundred, decade, unit };
        }
        /// 
        /// 获取发送位数据
        /// 
        /// 
        /// 
        private byte GetSendByteData(byte originalData)
        {
            return (byte)(ADD_FLAG + originalData);
        }
        
        
    }
}