using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using DH.Commons.Base;
using DH.Commons.Enums;
using HslCommunication;
using HslCommunication.Enthernet;
using HslCommunication.Profinet.XINJE;

namespace DH.Devices.PLC
{
    public class XinJEPLCTcpNet : PLCBase
    {
        private static XinJEPLCTcpNet _instance;
        public static XinJEPLCTcpNet Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new XinJEPLCTcpNet();
                return _instance;
            }
        }
    
        private XinJETcpNet TcpNet = new XinJETcpNet();

        public override bool PLCConnect()
        {
            try
            {
                TcpNet.IpAddress = IP;
                TcpNet.Port = Port;
                TcpNet.ConnectTimeOut = 5000;
                TcpNet.ReceiveTimeOut = 10000;
                TcpNet.SleepTime = 0;
                TcpNet.AddressStartWithZero = true;
                TcpNet.IsStringReverse = false;
                TcpNet.DataFormat = HslCommunication.Core.DataFormat.ABCD;
                TcpNet.Station = 1;
                TcpNet.Series = XinJESeries.XD;

                PLCItem itemSpeed = PLCItemList.FirstOrDefault(u => u.Name == "转盘速度");
                if(itemSpeed== null)
                {
                    return false;
                }
                OperateResult ret = TcpNet.ConnectServer();
                if (ret.IsSuccess)
                {
                    Connected = true;
                    MonitorPieces();

                    TurntableOpen(Convert.ToInt32(itemSpeed.Value) , true);

                    return true;
                }
                else
                {
                    return false;
                }


            }
            catch
            {
                return false;
            }

        }


        public override ushort ReadShort(string address)
        {
            try
            {
                // 读取Int变量
                var result = TcpNet.ReadInt16(address);
                if (result.IsSuccess)
                {
                    return (ushort)result.Content;
                }
                else
                {
                    return 0;
                }
            }
            catch (Exception ex)
            {

                return 0;
            }
        }



        public override int ReadInt(string address)
        {
            try
            {
                // 读取Int变量
                var result = TcpNet.ReadInt32(address);
                if (result.IsSuccess)
                {
                    return result.Content;
                }
                else
                {

                    return -1;
                }
            }
            catch (Exception ex)
            {
                return -1;
            }
        }


        public override float ReadFloat(string address)
        {
            try
            {
                // 读取Float变量
                var result = TcpNet.ReadFloat(address);
                if (result.IsSuccess)
                {
                    return result.Content;
                }
                else
                {
                    return -1;
                }
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public override bool ReadBool(string address)
        {
            try
            {
                // 读取Bool变量
                var result = TcpNet.ReadBool(address);
                if (result.IsSuccess)
                {
                    return result.Content;
                }
                else
                {
                    return false; // 或者可以考虑返回其他的错误标识符
                }
            }
            catch (Exception ex)
            {
                return false; // 或者返回其他的错误标识符
            }
        }


        /// <summary>
        /// 写单独地址 short 值
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="writeValue">要写入的 int 值</param>
        /// <param name="waitForReply">是否等待回复</param>
        public override bool WriteShort(string address, short writeValue, bool waitForReply = true)
        {
            if (string.IsNullOrEmpty(address))
            {
                return false;
            }

            int repeatTime = 3;
            Stopwatch sw = new Stopwatch();
            sw.Start();  // 启动计时

            do
            {
                try
                {
                    var result = TcpNet.Write(address, (short)writeValue);
                    if (result.IsSuccess)
                    {
                        sw.Stop();
                        //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{Name} {address},写入 {writeValue} 完成,耗时:{sw.ElapsedMilliseconds} ms");
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    repeatTime--;
                    if (repeatTime <= 0)
                    {
                        return false;
                    }
                }
            } while (repeatTime > 0);

            sw.Stop();
            return false;
        }


        /// <summary>
        /// 写单独地址 int 值
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="writeValue">要写入的 int 值</param>
        /// <param name="waitForReply">是否等待回复</param>
        public override bool WriteInt(string address, int writeValue, bool waitForReply = true)
        {
            if (string.IsNullOrEmpty(address))
            {
                return false;
            }

            int repeatTime = 3;
            Stopwatch sw = new Stopwatch();
            sw.Start();  // 启动计时

            do
            {
                try
                {
                    var result = TcpNet.Write(address, writeValue);
                    if (result.IsSuccess)
                    {
                        sw.Stop();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    repeatTime--;
                    if (repeatTime <= 0)
                    {
                        return false;
                    }
                }
            } while (repeatTime > 0);

            sw.Stop();
            return false;
        }



        /// <summary>
        /// 写单独地址 Dint 值
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="writeValue">要写入的 Dint 值</param>
        /// <param name="waitForReply">是否等待回复</param>
        public override bool WriteDInt(string address, int writeValue, bool waitForReply = true)
        {
            if (string.IsNullOrEmpty(address))
            {
                return false;
            }

            int repeatTime = 3;
            Stopwatch sw = new Stopwatch();
            sw.Start();  // 启动计时

            do
            {
                try
                {
                    string result = Regex.Replace(address, @"\D", "");
                    int r = Convert.ToInt32(result) + 1;
                    string address1 = "HD" + r.ToString();
                    short high = (short)(writeValue >> 16);  // 高 16 位
                    short low = (short)(writeValue & 0xFFFF);  // 低 16 位
                    TcpNet.Write(address1, high);
                    Thread.Sleep(10);
                    var res = TcpNet.Write(address, low);
                    if (res.IsSuccess)
                    {
                        sw.Stop();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    repeatTime--;
                    if (repeatTime <= 0)
                    {
                        return false;
                    }
                }
            } while (repeatTime > 0);

            sw.Stop();
            return false;
        }


        /// <summary>
        /// 写单独地址 float 值
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="writeValue">要写入的 float 值</param>
        /// <param name="waitForReply">是否等待回复</param>
        public override bool WriteFloat(string address, float writeValue, bool waitForReply = true)
        {
            if (string.IsNullOrEmpty(address))
            {
                return false;
            }

            int repeatTime = 3;
            Stopwatch sw = new Stopwatch();
            sw.Start();  // 启动计时

            do
            {
                try
                {
                    var result = TcpNet.Write(address, writeValue);
                    if (result.IsSuccess)
                    {
                        sw.Stop();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    repeatTime--;
                    if (repeatTime <= 0)
                    {
                        return false;
                    }
                }
            } while (repeatTime > 0);

            sw.Stop();
            return false;
        }

        /// <summary>
        /// 写单独地址 bool 值
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="writeValue">要写入的 bool 值</param>
        /// <param name="waitForReply">是否等待回复</param>
        public override bool WriteBool(string address, bool writeValue, bool waitForReply = true)
        {
            if (string.IsNullOrEmpty(address))
            {
                return false;
            }

            int repeatTime = 3;
            Stopwatch sw = new Stopwatch();
            sw.Start();  // 启动计时

            do
            {
                try
                {
                    var result = TcpNet.Write(address, writeValue);
                    if (result.IsSuccess)
                    {
                        sw.Stop();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    repeatTime--;
                    if (repeatTime <= 0)
                    {
                        return false;
                    }
                }
            } while (repeatTime > 0);

            sw.Stop();
            Thread.Sleep(10);
            return false;
        }


        public override bool PLCDisConnect()
        {
            if (Connected)
            {
                TurntableStop();
                var res = TcpNet.ConnectClose();
                if (res.IsSuccess)
                {
                    Connected = false;
                    return true;
                }
                return false;
            }
            return false;
        }




        private void MonitorPieces()
        {
        
            ThreadStart ts = new ThreadStart(MonitorPiecesImpl);
            Thread th = new Thread(ts);
            th.Priority = ThreadPriority.AboveNormal;
            th.IsBackground = false;
            th.Start();

        }


        public TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning);

        private Dictionary<ushort, uint> piecesCountDic = new Dictionary<ushort, uint>();
        private uint piecesCount = 0;

        /// <summary>
        /// int,int  轴号  捕获位置
        /// </summary>
        public event Action<int, uint> OnNewPieces;

        public void NewPieces(int axisIndex, uint pieceNumber)
        {
            _taskFactory.StartNew(() =>
            {
                Thread.CurrentThread.Priority = ThreadPriority.Highest;

                OnNewPieces?.Invoke(axisIndex, pieceNumber);
            });
        }
        /// <summary>
        /// 入料监听
        /// </summary>
        /// <param name="axisIndex"></param>
        private void MonitorPiecesImpl()
        {

            PLCItem pLCItem= PLCItemList.FirstOrDefault(u => u.Name == "产品计数");
            if (pLCItem == null)
                return;
            DateTime startTime = DateTime.Now;
            DateTime endTime = startTime;
            TimeSpan timeSpan = endTime - startTime;
            Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
            //while (CurrentState != DeviceState.DSClose && CurrentState != DeviceState.DSExcept && CurrentState != DeviceState.DSUninit)
            while (Connected)
            {
                Stopwatch sw = new Stopwatch();
                uint tmpPieceNumber = 0;
                sw.Start();
                
                var ret = TcpNet.ReadUInt16("D1016");

                sw.Stop();
                if (ret.IsSuccess)
                {
                    tmpPieceNumber = ret.Content;
                }

                if (ret.IsSuccess && ret.Content > piecesCount)
                {
                    sw.Start();
                    // Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")} 板卡{station}产品入列触发{tmpPieceNumber}");
                    //LogAsync(DateTime.Now, LogLevel.Information, $"转盘{0}产品入列 {piecesCountDic[0]} size:{sum}");
                    if (tmpPieceNumber != piecesCount + 1)
                    {
                        //LogAsync(DateTime.Now, LogLevel.Information, $"入列触发丢失\t{tmpPieceNumber}");
                        // Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}\t板卡{station}产品入列触发丢失,{piecesCountDic[station]}\t{tmpPieceNumber}");

                    }
                    piecesCount = tmpPieceNumber;
                    //NewPieces(ai, piecesCountDic[station]);
                     NewPieces(1, piecesCount);
                    sw.Stop();
                    startTime = DateTime.Now;
                    //if (idalarm)
                    //{
                    //    idalarm = false;
                    //    AlarmVibration(false);
                    //}

                }

                Thread.Sleep(1);
            }
        }




        /// <summary>
        /// 转盘开启操作
        /// </summary>
        public void TurntableOpen(int speed, bool Direction)
        {
            WriteBool("M122", true);
            Thread.Sleep(10);
            WriteBool("M10", false);
            Thread.Sleep(10);
            //速度
            TcpNet.Write("HD10", (ushort)speed);
            Thread.Sleep(10);
            //方向
            WriteBool("M1", Direction);
            Thread.Sleep(10);
            //使能
            WriteBool("M2", true);
            Thread.Sleep(10);
            //启动
            WriteBool("M0", true);
            Thread.Sleep(10);
            // _mainMotion.CurrentState = DeviceState.DSOpen;
            piecesCount = 0;
        }


        /// <summary>
        /// 转盘停止操作
        /// </summary>
        public void TurntableStop()
        {
            WriteBool("M122", true);
            Thread.Sleep(50);
            WriteBool("M0", false);
            Thread.Sleep(50);
            WriteBool("M2", false);
            Thread.Sleep(50);
            WriteBool("M50", false);
            piecesCount = 0;
        }

        /// <summary>
        /// 计数清零
        /// </summary>
        public void CountToZero()
        {
            WriteBool("M120", true);

        }
    }
}