using Common.Attributes;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using TSMaster;
namespace TSMasterCAN
{
    [ACPCommand]
    public class CAN : IDisposable
    {
        #region 静态成员

        public static event Action? ConnectEvent;
        public static event Action? DisConnectEvent;
        public static bool ConnectFlag { get; set; } = false;

        /// <summary>
        /// 实时接收到的 CAN 报文缓存（按报文 ID 索引，保留最新帧）。
        /// 供 CANViewModel.Refresh 等界面轮询读取。
        /// </summary>
        public static ConcurrentDictionary<int, TLIBCANFD> RealTimeMessages { get; } = new();

        #endregion

        #region 实例字段与属性

        /// <summary>设备类型号（43 = USBCANFD-400U 等，TSMaster 中作为配置参考保留）</summary>
        public uint DeviceType { get; }
        /// <summary>设备索引</summary>
        public uint DeviceIndex { get; }
        /// <summary>最大通道数</summary>
        public int MaxChannels { get; }
        /// <summary>仲裁域波特率</summary>
        public string ABitBaud { get; }
        /// <summary>数据域波特率</summary>
        public string DBitBaud { get; }
        /// <summary>是否开启终端电阻</summary>
        public bool EnableTerminalResistance { get; }

        /// <summary>DBC 解析器（提供 MsgDatabase、MaxChannels 等访问）</summary>
        public DBCParse DBCParser => DBCParse.Instance;

        /// <summary>
        /// DBC 报文解码事件：当接收到 CAN 帧并通过 DBC 解码后触发。
        /// 参数：(通道号, 解码后的报文信息)
        /// </summary>
        public event Action<uint, DBCMessage>? OnDbcMessageDecoded;

        private bool _disposed;
        private bool _isOpened;
        private TCANFDQueueEvent_Win32? _instanceListener;

        #endregion

        #region 构造函数

        /// <summary>默认构造函数（兼容 SystemConfig.CANFD = new() 等场景）</summary>
        public CAN() : this(43, 0, 4, "500000", "2000000", true) { }

        /// <summary>
        /// 带配置参数的构造函数（兼容原 ZLG 设备管理流程）。
        /// </summary>
        /// <param name="deviceType">设备类型号</param>
        /// <param name="deviceIndex">设备索引</param>
        /// <param name="maxChannels">最大通道数</param>
        /// <param name="aBitBaud">仲裁域波特率</param>
        /// <param name="dBitBaud">数据域波特率</param>
        /// <param name="enableTerminalResistance">是否开启终端电阻</param>
        public CAN(uint deviceType, uint deviceIndex, int maxChannels, string aBitBaud, string dBitBaud, bool enableTerminalResistance)
        {
            DeviceType = deviceType;
            DeviceIndex = deviceIndex;
            MaxChannels = maxChannels;
            ABitBaud = aBitBaud;
            DBitBaud = dBitBaud;
            EnableTerminalResistance = enableTerminalResistance;
        }

        #endregion

        #region 实例方法 — 设备管理（替代原 ZLG 实例方法）

        /// <summary>
        /// 打开设备：初始化 TSMaster 库 → 设置通道数 → 配置波特率 → 连接 → 启动 RBS → 注册监听。
        /// </summary>
        /// <returns>true 表示成功</returns>
        public bool 打开设备()
        {
            if (_isOpened) return true;
            if (ConnectFlag) { _isOpened = true; return true; }

            try
            {
                // 1. 初始化 TSMaster 库
                var re = Init("ACP");
                if (re != 0)
                {
                    Debug.WriteLine($"TSMaster 初始化失败,错误代码：{re}");
                    return false;
                }

                // 2. 设置通道数
                TsMasterApi.tsapp_set_can_channel_count(MaxChannels);

                // 3. 配置各通道波特率
                float arbKbps = float.Parse(ABitBaud) / 1000f;
                float dataKbps = float.Parse(DBitBaud) / 1000f;
                for (int ch = 0; ch < MaxChannels; ch++)
                {
                    TsMasterApi.tsapp_configure_baudrate_canfd(
                        ch, arbKbps, dataKbps,
                        TLIBCANFDControllerType.lfdtISOCAN,
                        TLIBCANFDControllerMode.lfdmNormal,
                        EnableTerminalResistance);
                }

                // 4. 连接硬件
                re = Connect();
                if (re != 0)
                {
                    Debug.WriteLine($"CAN 连接失败,错误代码：{re}");
                    return false;
                }

                // 5. 注册接收监听（用于 DBC 信号解码广播）
                _instanceListener = new TCANFDQueueEvent_Win32(OnCanFdReceived);
                RegisterListener(_instanceListener);

                _isOpened = true;
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"打开设备异常：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 关闭 CAN 卡设备：注销监听 → 断开连接。
        /// </summary>
        public void 关闭CAN卡设备()
        {
            if (!_isOpened && !ConnectFlag) return;

            try
            {
                if (_instanceListener != null)
                {
                    UnRegisterListener(_instanceListener);
                    _instanceListener = null;
                }
                DisConnect();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"关闭CAN卡设备异常：{ex.Message}");
            }
            finally
            {
                _isOpened = false;
            }
        }

        /// <summary>
        /// 初始化并启动指定通道（配置波特率，TSMaster 在 Connect 时已自动启动所有通道）。
        /// </summary>
        /// <param name="channel">通道号</param>
        public void 初始化并启动通道(uint channel)
        {
            if (channel >= MaxChannels) return;
            try
            {
                float arbKbps = float.Parse(ABitBaud) / 1000f;
                float dataKbps = float.Parse(DBitBaud) / 1000f;
                TsMasterApi.tsapp_configure_baudrate_canfd(
                    (int)channel, arbKbps, dataKbps,
                    TLIBCANFDControllerType.lfdtISOCAN,
                    TLIBCANFDControllerMode.lfdmNormal,
                    EnableTerminalResistance);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"初始化通道 {channel} 异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 加载通道 DBC 文件。
        /// </summary>
        /// <param name="channel">通道号</param>
        /// <param name="filePath">DBC 文件路径</param>
        /// <returns>true 表示加载成功</returns>
        public bool 加载通道DBC文件(uint channel, string filePath)
        {
            try
            {
                var re = LoadDBC(filePath, [(int)channel], out _);
                return re == 0;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"加载通道 {channel} DBC 文件异常：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// CAN FD 接收回调：接收原始帧 → 查找 DBC → 解码信号 → 触发 OnDbcMessageDecoded 事件。
        /// </summary>
        private void OnCanFdReceived(ref int AObj, ref TLIBCANFD AData)
        {
            if (_disposed) return;

            // 始终缓存最新报文，供界面轮询刷新
            int identifier = AData.FIdentifier;
            var canfdCopy = AData;
            RealTimeMessages[identifier] = canfdCopy;

            if (OnDbcMessageDecoded == null) return;

            try
            {
                uint channel = AData.FIdxChn;
                if (channel >= DBCParse.MsgDatabase.Count) return;

                // 在 DBC 数据库中查找匹配的报文
                var msgList = DBCParse.MsgDatabase[(int)channel];
                var match = msgList.FirstOrDefault(m => m.msg_id == identifier);
                if (match == null || match.signal_Name == null || match.signal_Name.Length == 0) return;

                // 解码各信号值
                var signals = new DBCSignal[match.signal_Name.Length];
                for (int i = 0; i < match.signal_Name.Length; i++)
                {
                    double value = 0;
                    TsMasterApi.tsdb_get_signal_value_canfd(ref canfdCopy, match.msg_name, match.signal_Name[i], ref value);
                    signals[i] = new DBCSignal
                    {
                        strName = Encoding.Default.GetBytes(match.signal_Name[i]),
                        nRawvalue = value,
                        nFactor = 1,
                        nOffset = 0
                    };
                }

                var decoded = new DBCMessage
                {
                    nID = (uint)identifier,
                    nSignalCount = signals.Length,
                    vSignals = signals
                };

                OnDbcMessageDecoded?.Invoke(channel, decoded);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"DBC 信号解码异常：{ex.Message}");
            }
        }

        #endregion

        #region IDisposable

        public void Dispose()
        {
            if (_disposed) return;
            _disposed = true;
            关闭CAN卡设备();
            GC.SuppressFinalize(this);
        }

        #endregion

        /// <summary>
        /// 初始化TSMasterCAN
        /// </summary>
        /// <param name="ProjectName"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [Browsable(false)]
        public static int Init(string ProjectName, string? filePath = null)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return TsMasterApi.initialize_lib_tsmaster(ProjectName);
            }
            else
            {
                return TsMasterApi.initialize_lib_tsmaster_with_project(ProjectName, Path.GetFullPath(filePath));
            }
        }

        /// <summary>
        /// 释放TSMasterCAN
        /// </summary>
        [Browsable(false)]
        public static void Release()
        {
            TsMasterApi.finalize_lib_tsmaster();
        }

        public static int obj = 0;
        public static TCANFDQueueEvent_Win32 listener;
        [Browsable(false)]
        public static int RegisterListener(TCANFDQueueEvent_Win32 listenEvent)
        {
            listener = listenEvent;
            var re = TsMasterApi.tsapp_register_event_canfd(ref obj, listener);
            Debug.Assert(re == 0);
            return re;
        }

        [Browsable(false)]
        public static int UnRegisterListener(TCANFDQueueEvent_Win32 listenEvent = null)
        {
            if (listenEvent is not null)
            {
                listener = listenEvent;
            }
            var re = TsMasterApi.tsapp_unregister_event_canfd(ref obj, listener);
            Debug.Assert(re == 0);
            return re;
        }

        /// <summary>
        /// 连接
        /// </summary>
        /// <returns></returns>
        public static int Connect()
        {

            var re = TsMasterApi.tsapp_connect();
            if (re == 0)
            {
                re = TsMasterApi.tscom_can_rbs_start();
                if (re == 0)
                {
                    ConnectFlag = true;
                    Task.Run(() => ConnectEvent?.Invoke());
                }
                else
                {
                    Debug.WriteLine($"CAN_RBS启动失败,错误代码：{re}");
                }
            }
            else
            {
                Debug.WriteLine($"CAN连接失败,错误代码：{re}");
                return re;
            }
            return re;
        }

        /// <summary>
        /// 断开
        /// </summary>
        /// <returns></returns>
        public static int DisConnect()
        {
            var re = TsMasterApi.tsapp_disconnect();
            //Debug.Assert(re == 0);
            if (re == 0)
            {
                ConnectFlag = false;
                Task.Run(() => DisConnectEvent?.Invoke());
            }
            else
            {
                Debug.WriteLine($"断开CAN连接失败,错误代码：{re}");
            }


            return re;
        }

        /// <summary>
        /// 加载DBC
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="channel"></param>
        /// <param name="databaseID"></param>
        /// <returns></returns>
        [Browsable(false)]
        public static int LoadDBC(string filePath, int[] channel, out uint databaseID)
        {
            databaseID = 0;

            var re = TsMasterApi.tsdb_load_can_db(Path.GetFullPath(filePath), string.Join(",", channel), ref databaseID);
            foreach (var item in channel)
            {
                DBCParse.parse(databaseID, item);
                DBCParse.rbs_parse(databaseID, item);
            }

            return re;
        }

        /// <summary>
        /// 卸载DBC
        /// </summary>
        /// <param name="databaseID"></param>
        /// <returns></returns>
        [Browsable(false)]
        public static int UnLoadDBC(uint? databaseID = null)
        {
            if (databaseID == null)
            {
                return TsMasterApi.tsdb_unload_can_dbs();
            }
            else
            {
                return TsMasterApi.tsdb_unload_can_db(databaseID.Value);
            }
        }

        /// <summary>
        /// 开始记录日志
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static int StartLogging(string filePath)
        {
            return TsMasterApi.tsapp_start_logging(Path.GetFullPath(filePath));
        }

        /// <summary>
        /// 结束记录日志
        /// </summary>
        /// <returns></returns>
        public static int StopLogging()
        {
            return TsMasterApi.tsapp_stop_logging();
        }

        /// <summary>
        /// 弹出通道映射窗口
        /// </summary>
        /// <param name="isWait"></param>
        /// <returns></returns>
        [Browsable(false)]
        public static int ShowChannelMappingWindow(bool isWait = false)
        {
            return TsMasterApi.tsapp_show_tsmaster_window("Hardware", isWait);
        }

        /// <summary>
        /// 获取信号值
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="AMsgName"></param>
        /// <param name="ASgnName"></param>
        /// <returns></returns>
        public static double GetSignalValue(byte channel, string AMsgName, string ASgnName)
        {
            double value = double.NaN;
            var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName);
            var re = TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value);

            return value;
        }

        /// <summary>
        /// 获取信号值
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="AMsgName"></param>
        /// <param name="ASgnName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        [Browsable(false)]
        public static int GetSignalValue(byte channel, string AMsgName, string ASgnName, ref double value)
        {
            var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName);
            return TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value);
        }

        /// <summary>
        /// 获取信号值
        /// </summary>
        /// <param name="ACANFD"></param>
        /// <param name="AMsgName"></param>
        /// <param name="ASgnName"></param>
        /// <param name="value"></param>
        /// <returns></returns>

        [Browsable(false)]
        public static int GetSignalValue(ref TLIBCANFD ACANFD, string AMsgName, string ASgnName, ref double value)
        {
            return TsMasterApi.tsdb_get_signal_value_canfd(ref ACANFD, AMsgName, ASgnName, ref value);
        }

        /// <summary>
        /// 设置信号值
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="AMsgName"></param>
        /// <param name="ASgnName"></param>
        /// <param name="AValue"></param>
        /// <param name="isSend"></param>
        /// <param name="sendPeriod"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static int SetSignalValue(byte channel, string AMsgName, string ASgnName, double AValue, bool isSend = false, float sendPeriod = 0)
        {
            var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName);
            find.ACANFD.FIdxChn = channel;
            var re = TsMasterApi.tsdb_set_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, AValue);
            Debug.Assert(re == 0);
            if (re != 0) throw new Exception($"设置报文失败!返回代码{re}");
            if (re != 0) return re;
            if (isSend)
            {
                if (sendPeriod == 0)
                {
                    return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD);
                }
                else
                {
                    return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
                }
            }
            return 0;
        }

        
        /// <summary>
        /// 设置信号值
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="AMsgName"></param>
        /// <param name="sendPeriod"></param>
        /// <returns></returns>
        public static int SetSignalValue(APP_CHANNEL channel, string AMsgName, float sendPeriod = 0)
        {
            var find = DBCParse.MsgDatabase[(byte)channel].First(s => s.msg_name == AMsgName);
            find.ACANFD.FIdxChn = (byte)channel;
            if (sendPeriod == 0)
            {
                return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD);
            }
            else
            {
                return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
            }
        }

        /// <summary>
        /// 发送自定义报文
        /// </summary>
        /// <returns></returns>
        [Browsable(false)]
        public static int SetMsg(TLIBCANFD msg)
        {
            return TsMasterApi.tsapp_transmit_canfd_async(ref msg);
        }

        /// <summary>
        /// 设置报文
        /// </summary>
        /// <param name="channel">通道</param>
        /// <param name="ID">DBC数据库ID</param>
        /// <param name="bytes">报文数组</param>
        public static void SetMsg(APP_CHANNEL channel, int ID, byte[] bytes)
        {
            var find = DBCParse.MsgDatabase[(byte)channel].FirstOrDefault(s => s.ACANFD.FIdentifier == ID);
            if (find != null)
            {
                Array.Copy(bytes, 0, find.ACANFD.FData, 0, Math.Min(bytes.Length, find.ACANFD.FData.Length));
            }
        }

        /// <summary>
        /// 发送自定义报文
        /// </summary>
        /// <param name="AIdxChn"></param>
        /// <param name="AID"></param>
        /// <param name="AIsTx"></param>
        /// <param name="AIsExt"></param>
        /// <param name="AIsRemote"></param>
        /// <param name="ADLC"></param>
        /// <param name="ADataArray"></param>
        /// <param name="AIsFD"></param>
        /// <param name="AIsBRS"></param>
        /// <param name="isUpdateDBCDatabase"></param>
        /// <param name="sendPeriod"></param>
        /// <returns></returns>
        public static int SendMsg(APP_CHANNEL AIdxChn, int AID, bool AIsTx, bool AIsExt,
            bool AIsRemote, byte ADLC, byte[] ADataArray, bool AIsFD = true, bool AIsBRS = false,
            bool isUpdateDBCDatabase = false, float sendPeriod = 0)
        {
            var send = new TLIBCANFD
            {
                FIdxChn = (byte)AIdxChn,
                FProperties = 0,
                FIdentifier = AID,
                FDLC = ADLC,
                FTimeUS = 0uL,
                FData = new byte[64],
                FFDProperties = 0,
                FIsTx = AIsTx,
                FIsError = false,
                FIsExt = AIsExt,
                FIsRemote = AIsRemote,
                FIsFD = AIsFD,
                FIsBRS = AIsBRS
            };
            int length = Math.Min(ADataArray.Length, 64);
            Array.Copy(ADataArray, 0, send.FData, 0, length);
            int re;
            if (sendPeriod == 0)
            {
                re = TsMasterApi.tsapp_transmit_canfd_async(ref send);
            }
            else
            {
                re = TsMasterApi.tsapp_add_cyclic_msg_canfd(ref send, sendPeriod);
            }

            if (isUpdateDBCDatabase)
            {
                var find = DBCParse.MsgDatabase[(byte)AIdxChn].FirstOrDefault(s => s.ACANFD.FIdentifier == send.FIdentifier);
                if (find != null)
                {
                    Array.Copy(send.FData, 0, find.ACANFD.FData, 0, Math.Min(ADataArray.Length, find.ACANFD.FData.Length));
                }
            }
            return re;
        }

        /// <summary>
        /// 添加循环发送报文
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="AMsgName"></param>
        /// <param name="sendPeriod"></param>
        /// <returns></returns>
        public static int AddCyclicMsg(byte channel, string AMsgName, float sendPeriod)
        {
            var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName);
            find.ACANFD.FIdxChn = channel;
            return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
        }

        /// <summary>
        /// 清除循环发送的报文
        /// </summary>
        /// <returns></returns>
        public static int DeleteCyclicMsgs()
        {
            return TsMasterApi.tsapp_delete_cyclic_msgs();
        }

        /// <summary>
        /// 获取错误提示
        /// </summary>
        /// <param name="errorCode">错误代码</param>
        /// <returns></returns>
        public static string GetErrorDescription(int errorCode)
        {
            IntPtr ADesc = IntPtr.Zero;
            TsMasterApi.tsapp_get_error_description(errorCode, ref ADesc);

            if (ADesc == IntPtr.Zero) return $"未知错误代码: {errorCode}";

            // 假设返回的是 ANSI 字符串（如 C 的 char*）
            string? description = Marshal.PtrToStringAnsi(ADesc);

            return description ?? $"未知错误代码: {errorCode}";
        }

    }
}
