using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ZLGUSBCANFD
{
    public class _Msg_
    {
        public int msg_type { get; set; }
        public int msg_id { get; set; }
        public int msg_cyclic { get; set; }
        public byte msg_dlc { get; set; }
        public string msg_name { get; set; }
        public string[] signal_Name { get; set; }
        public int msg_brs { get; set; }
    }

    public enum Msg_Type
    {
        CAN = 0,
        CANFD = 1,
    }

    /// <summary>
    /// DBC 报文解析器（实例类，每个 ZLGCANFD 拥有独立的解析器实例）。
    /// 不同 CAN 卡的作用域各自维护自己的 MsgDatabase，互不干扰。
    /// </summary>
    public class ZLGDBCParser
    {
        /// <summary>
        /// 每个通道的报文数据库缓存，供 ViewModel 直接读取。
        /// 索引 = 通道号 (0 ~ maxChannels-1)。
        /// </summary>
        public List<List<_Msg_>> MsgDatabase { get; private set; }

        /// <summary>
        /// 最大通道数（与所属 ZLGCANFD 一致）。
        /// </summary>
        public int MaxChannels { get; }

        public ZLGDBCParser(int maxChannels = 4)
        {
            MaxChannels = maxChannels;
            MsgDatabase = new List<List<_Msg_>>(
                Enumerable.Range(0, maxChannels).Select(_ => new List<_Msg_>())
            );
        }

        /// <summary>
        /// 解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中。
        /// </summary>
        /// <param name="chDbcHandle">ZDBC 句柄</param>
        /// <param name="channel">通道号索引 (0 ~ maxChannels-1)</param>
        public void ParseAndLoadToDatabase(uint chDbcHandle, int channel)
        {
            if (channel < 0 || channel >= MsgDatabase.Count) return;

            // 清空当前通道旧缓存
            MsgDatabase[channel].Clear();

            // 解析并填充
            var parsedList = ParseZlgDbc(chDbcHandle);
            MsgDatabase[channel].AddRange(parsedList);
        }

        /// <summary>
        /// 全手工解析周立功 DBC 句柄下的所有消息和信号。
        /// </summary>
        /// <param name="chDbcHandle">对应通道的 ZDBC 句柄</param>
        /// <returns>返回对齐同星业务层的自定义报文列表</returns>
        public static List<_Msg_> ParseZlgDbc(uint chDbcHandle)
        {
            List<_Msg_> msgList = new List<_Msg_>();

            if (chDbcHandle == 0 || chDbcHandle == ZDBC.INVALID_DBC_HANDLE)
                return msgList;

            int msgSize = Marshal.SizeOf(typeof(ZDBC.DBCMessage));
            IntPtr pMsg = Marshal.AllocHGlobal(msgSize);

            try
            {
                bool hasMessage = ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg);

                while (hasMessage)
                {
                    var zlgMsg = (ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZDBC.DBCMessage));

                    int nullIndex = Array.IndexOf(zlgMsg.strName, (byte)0);

                    _Msg_ myMsg = new _Msg_
                    {
                        msg_id = (int)zlgMsg.nID,
                        msg_name = nullIndex >= 0
                            ? Encoding.Default.GetString(zlgMsg.strName, 0, nullIndex)
                            : Encoding.Default.GetString(zlgMsg.strName).TrimEnd('\0'),
                        msg_dlc = (byte)zlgMsg.nSize,
                        msg_cyclic = (int)zlgMsg.nCycleTime,
                        msg_type = zlgMsg.nExtend == 1 ? (int)Msg_Type.CANFD : (int)Msg_Type.CAN,
                        signal_Name = new string[zlgMsg.nSignalCount]
                    };

                    for (int i = 0; i < zlgMsg.nSignalCount; i++)
                    {
                        var signal = zlgMsg.vSignals[i];
                        string sigName = Encoding.Default.GetString(signal.strName).TrimEnd('\0');
                        myMsg.signal_Name[i] = sigName;
                    }

                    msgList.Add(myMsg);
                    hasMessage = ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(pMsg);
            }

            msgList.Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
            return msgList;
        }
    }
}
