using rokae.clr;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using rokae.clr;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
using static rokae.clr.ArcWelding;
using static rokae.clr.xPanelOpt;
using EventInfos = System.Collections.Generic.Dictionary<System.String, System.Object>;
using System.Collections;

namespace xCoreSDK_CSharp.examples
{
    public class XCoreStatus
    {
        // ----- 基础信息 -----
        public int MsgSize { get; set; }      // 0-3
        public ulong Ts { get; set; }         // 4-11
        public byte PowerSt { get; set; }     // 12
        public byte RobotBusy { get; set; }   // 13
        public byte OperationSt { get; set; } // 14
        public byte OperateMode { get; set; } // 15
        public byte CollisionSt { get; set; } // 16
        public byte CollaborateMode { get; set; } // 17
        public byte SdkConnection { get; set; }   // 18
        public int LogCode { get; set; }      // 19-22

        // ----- 关节数据 -----
        public List<double> QM { get; set; }      // 23-78 (7 doubles)
        public List<double> DqM { get; set; }     // 79-134 (7 doubles)
        public List<double> TauM { get; set; }    // 135-190 (7 doubles)

        // ----- 外部轴数据 -----
        public List<double> ExQM { get; set; }    // 191-238 (6 doubles)
        public List<double> ExDqM { get; set; }   // 239-286 (6 doubles)

        // ----- 坐标系数据 -----
        public List<double> PosEirM { get; set; } // 287-334 (6 doubles)
        public List<double> PosFibM { get; set; } // 335-382 (6 doubles)
        public List<double> ToolFrame { get; set; } // 383-430 (6 doubles)
        public List<double> WobjFrame { get; set; } // 431-478 (6 doubles)

        // ----- IO信号 -----
        public ushort DioBoard0Di { get; set; } // 479-480 (小端)
        public ushort DioBoard0Do { get; set; } // 481-482 
        public ushort DioBoard1Di { get; set; } // 483-484 
        public ushort DioBoard1Do { get; set; } // 485-486 
        public ushort DioBoard2Di { get; set; } // 487-488 
        public ushort DioBoard2Do { get; set; } // 489-490 

        // ----- IO信号数组 -----
        public List<int> DioBoard0DiArray { get; set; }
        public List<int> DioBoard0DoArray { get; set; }
        public List<int> DioBoard1DiArray { get; set; }
        public List<int> DioBoard1DoArray { get; set; }
        public List<int> DioBoard2DiArray { get; set; }
        public List<int> DioBoard2DoArray { get; set; }

        // ----- 模拟信号 -----
        public List<double> AioBoard0Ai { get; set; } // 491-538 (6 doubles)
        public List<double> AioBoard0Ao { get; set; } // 539-586 
        public List<double> AioBoard1Ai { get; set; } // 587-634 
        public List<double> AioBoard1Ao { get; set; } // 635-682 

        // ----- 状态信号 -----
        public byte XpanelKeypad { get; set; } // 683
        public byte FaultSr { get; set; }      // 684
        public List<int> ServoAlarm { get; set; } // 685-712 (7 int32)
        public byte RlProgRunning { get; set; } // 713
        public double SpeedRatio { get; set; } // 714-721 
        public byte V { get; set; }            // 722
    }
    public class ParseDataDemo
    {
        public XCoreStatus ParseXCoreData(byte[] data)
        {
            if (data.Length != 723)
                throw new ArgumentException($"数据长度错误，期望723字节，实际收到{data.Length}字节");

            using (var ms = new MemoryStream(data))
            using (var reader = new BinaryReader(ms))
            {
                var status = new XCoreStatus();

                // ----- 基础信息 -----
                ms.Position = 0;
                status.MsgSize = ReadInt32LittleEndian(reader); // <i

                ms.Position = 4;
                status.Ts = ReadUInt64LittleEndian(reader);     // <Q

                ms.Position = 12;
                status.PowerSt = reader.ReadByte();
                status.RobotBusy = reader.ReadByte();
                status.OperationSt = reader.ReadByte();
                status.OperateMode = reader.ReadByte();
                status.CollisionSt = reader.ReadByte();
                status.CollaborateMode = reader.ReadByte();
                status.SdkConnection = reader.ReadByte();

                ms.Position = 19;
                status.LogCode = ReadInt32LittleEndian(reader); // <i

                // ----- 关节数据 -----
                status.QM = ReadDoubleArray(reader, 23, 7);
                status.DqM = ReadDoubleArray(reader, 79, 7);
                status.TauM = ReadDoubleArray(reader, 135, 7);

                // ----- 外部轴数据 -----
                status.ExQM = ReadDoubleArray(reader, 191, 6);
                status.ExDqM = ReadDoubleArray(reader, 239, 6);

                // ----- 坐标系数据 -----
                status.PosEirM = ReadDoubleArray(reader, 287, 6);
                status.PosFibM = ReadDoubleArray(reader, 335, 6);
                status.ToolFrame = ReadDoubleArray(reader, 383, 6);
                status.WobjFrame = ReadDoubleArray(reader, 431, 6);

                // ----- IO信号 -----
                status.DioBoard0Di = ReadUInt16LittleEndian(reader, 479);
                status.DioBoard0Do = ReadUInt16LittleEndian(reader, 481);
                status.DioBoard1Di = ReadUInt16LittleEndian(reader, 483);
                status.DioBoard1Do = ReadUInt16LittleEndian(reader, 485);
                status.DioBoard2Di = ReadUInt16LittleEndian(reader, 487);
                status.DioBoard2Do = ReadUInt16LittleEndian(reader, 489);

                // ----- IO信号数组 -----
                status.DioBoard0DiArray = GetIOArray(status.DioBoard0Di);
                status.DioBoard0DoArray = GetIOArray(status.DioBoard0Do);
                status.DioBoard1DiArray = GetIOArray(status.DioBoard1Di);
                status.DioBoard1DoArray = GetIOArray(status.DioBoard1Do);
                status.DioBoard2DiArray = GetIOArray(status.DioBoard2Di);
                status.DioBoard2DoArray = GetIOArray(status.DioBoard2Do);

                // ----- 模拟信号 -----
                status.AioBoard0Ai = ReadDoubleArray(reader, 491, 6);
                status.AioBoard0Ao = ReadDoubleArray(reader, 539, 6);
                status.AioBoard1Ai = ReadDoubleArray(reader, 587, 6);
                status.AioBoard1Ao = ReadDoubleArray(reader, 635, 6);

                // ----- 状态信号 -----
                ms.Position = 683;
                status.XpanelKeypad = reader.ReadByte();
                status.FaultSr = reader.ReadByte();

                status.ServoAlarm = ReadInt32Array(reader, 685, 7);

                ms.Position = 713;
                status.RlProgRunning = reader.ReadByte();

                ms.Position = 714;
                status.SpeedRatio = ReadDoubleLittleEndian(reader);

                ms.Position = 722;
                status.V = reader.ReadByte();

                return status;
            }
        }

        // 辅助方法：读取小端序int32
        private static int ReadInt32LittleEndian(BinaryReader reader)
        {
            byte[] bytes = reader.ReadBytes(4);
            return BitConverter.ToInt32(bytes, 0);
        }

        // 读取小端序uint64
        private static ulong ReadUInt64LittleEndian(BinaryReader reader)
        {
            byte[] bytes = reader.ReadBytes(8);
            return BitConverter.ToUInt64(bytes, 0);
        }

        // 读取小端序uint16
        private static ushort ReadUInt16LittleEndian(BinaryReader reader, int offset)
        {
            reader.BaseStream.Position = offset;
            byte[] bytes = reader.ReadBytes(2);
            return BitConverter.ToUInt16(bytes, 0);
        }

        // 读取double数组
        private static List<double> ReadDoubleArray(BinaryReader reader, int offset, int count)
        {
            List<double> list = new List<double>();
            reader.BaseStream.Position = offset;
            for (int i = 0; i < count; i++)
            {
                list.Add(reader.ReadDouble());
            }
            return list;
        }

        // 读取int32数组
        private static List<int> ReadInt32Array(BinaryReader reader, int offset, int count)
        {
            List<int> list = new List<int>();
            reader.BaseStream.Position = offset;
            for (int i = 0; i < count; i++)
            {
                list.Add(reader.ReadInt32());
            }
            return list;
        }

        // 读取小端序double
        private static double ReadDoubleLittleEndian(BinaryReader reader)
        {
            byte[] bytes = reader.ReadBytes(8);
            return BitConverter.ToDouble(bytes, 0);
        }

        // 将IO信号转换为位数组
        private static List<int> GetIOArray(ushort value)
        {
            List<int> bits = new List<int>();
            for (int i = 0; i < 16; i++)
            {
                bits.Add((value >> i) & 1);
            }
            return bits;
        }

        public void PrintProperties(object obj)
        {
            foreach (var prop in obj.GetType().GetProperties())
            {
                var value = prop.GetValue(obj);
                if (value is IEnumerable enumerable && !(value is string))
                {
                    Debug.Write($"{prop.Name}: [");
                    foreach (var item in enumerable)
                    {
                        Debug.Write($"  {item},");
                    }
                    Debug.WriteLine("]");
                }
                else
                {
                    Debug.WriteLine($"{prop.Name}: {value}");
                }
            }
        }
        public void Demo()
        {
            string remoteIp = "192.168.110.129";
            int remotePort = 16666;

            try
            {
                xMateRobot robot = new xMateRobot("192.168.110.129");
                ErrorCode ec = new ErrorCode(0, "");
                robot.stopReceiveRobotState_Nrt(out ec);
                Debug.WriteLine("stopReceiveRobotState_Nrt", ec);
                List<string> extend = new List<string>();
                robot.startReceiveRobotState_Nrt(100,extend,16666, out ec);
                Debug.WriteLine("startReceiveRobotState_Nrt", ec);
                List<string> cliend_addr = new List<string>();
                var ret = robot.queryStateDataPublisherServerInfo(cliend_addr, out ec);
                switch (ret)
                {
                    case 0:
                        Debug.WriteLine("服务端监听中");
                        break;
                        case 2:
                        Debug.WriteLine("服务端已连接");
                        break;
                    case 3:
                        Debug.WriteLine("服务端已关闭");
                        break ;
                    default:
                        Debug.WriteLine("发生错误");
                        break;
                }

                using (TcpClient client = new TcpClient(remoteIp, remotePort))
                using (NetworkStream stream = client.GetStream())
                {
                    Debug.WriteLine($"成功连接到 {remoteIp}:{remotePort}");

                    byte[] buffer = new byte[723];
                    while (true)
                    {
                        int bytesRead = 0;
                        while (bytesRead < 723)
                        {
                            int read = stream.Read(buffer, bytesRead, 723 - bytesRead);
                            if (read == 0)
                                throw new Exception("连接已关闭");
                            bytesRead += read;
                        }

                        XCoreStatus status = ParseXCoreData(buffer);

                        // 打印示例字段
                        Debug.WriteLine($"时间戳: {status.Ts}");
                        Debug.WriteLine($"关节角度: {string.Join(", ", status.QM)}");
                        Debug.WriteLine($"IO板0 DI信号: {Convert.ToString(status.DioBoard0Di, 2)}");

                        // 打印所有属性
                        PrintProperties(status);

                        System.Threading.Thread.Sleep(100);
                    }
                }
            }
            catch (SocketException ex)
            {
                Debug.WriteLine($"无法连接到 {remoteIp}:{remotePort} - {ex.Message}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"发生错误: {ex.Message}");
            }
        }
    }

    
}
