using Serilog;
using Ayay.SerilogLogs;

namespace SHH.CameraSdk;

/// <summary>
/// [驱动支持层] 大华 SDK 全局资源管理器
/// 职责：统一管理大华 NetSDK 与 PlaySDK 的生命周期与预热
/// </summary>
public static class DahuaSdkManager
{
    #region --- 全局状态与锁 (Global States & Locks) ---
    /// <summary>
    /// 全局引用计数器。
    /// 只有当计数从 0 变 1 时才进行物理初始化，从 1 变 0 时才物理卸载。
    /// </summary>
    private static int _referenceCount = 0;

    /// <summary>
    /// 静态同步锁。
    /// 用于保护 _referenceCount 的原子操作，防止多线程并发 Start/Stop 时导致的初始化冲突。
    /// </summary>
    private static readonly object _lock = new();

    /// <summary>
    /// 播放库预热状态标记。
    /// 用于避免重复执行硬件探测（首次预热后后续直接返回）。
    /// </summary>
    private static bool _isWarmedUp = false;

    #endregion

    // 静态回调引用，防止被 GC
    private static fDisConnectCallBack m_DisConnectCallBack = (lLoginID, pchDVRIP, nDVRPort, dwUser) => { };

    #region --- SDK 初始化与卸载 (SDK Initialization & Uninstallation) ---

    /// <summary>
    /// 全局初始化大华 SDK 环境。
    /// <para>此方法是幂等的，内部会自动增加引用计数，支持多线程并发调用。</para>
    /// </summary>
    /// <returns>初始化成功返回 true；若 SDK 核心组件（HCNetSDK.dll）加载失败则返回 false。</returns>
    public static bool Initialize()
    {
        lock (_lock)
        {
            // 引用计数为 0 时执行物理初始化（仅首次调用时触发）
            if (_referenceCount == 0)
            {
                // [物理初始化] 大华 NetSDK 初始化
                // 注意：NETClient.Init 在某些版本下若重复调用会返回 false，需小心处理
                try
                {
                    NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null);
                    // 设置一些全局超时参数，提升工业响应速度
                    // NETClient.SetConnectTime(3000, 1); 
                }
                catch { return false; }
            }
            _referenceCount++;
            return true;
        }
    }

    /// <summary>
    /// 全局卸载大华 SDK 环境。
    /// <para>当所有相机实例都停止并释放后（引用计数归 0），会真正释放非托管资源。</para>
    /// </summary>
    public static void Uninitialize()
    {
        lock (_lock)
        {
            if (_referenceCount > 0)
            {
                _referenceCount--;
                if (_referenceCount == 0)
                {
                    // [物理卸载] 只有在没有实例使用时才彻底 Cleanup
                    // NETClient.Cleanup(); 
                }
            }
        }
    }

    #endregion

    #region --- 播放库预热 (PlayCtrl Warm-up) ---

    /// <summary>
    /// [核心策略] 大华播放库预热
    /// 职责：诱发 play.dll 完成底层硬件环境探测，规避取流瞬间的卡顿
    /// </summary>
    public static void ForceWarmUp()
    {
        if (_isWarmedUp) return;

        Log.ForContext("SourceContext", LogModules.Core)
            .Debug("[Dahua] 正在进行大华播放库硬件探测预热...");

        Stopwatch sw = Stopwatch.StartNew();
        int tempPort = -1;

        // 诱发点：PLAY_GetFreePort
        if (DahuaPlaySDK.PLAY_GetFreePort(ref tempPort))
        {
            // 大华的端口释放也必须及时
            DahuaPlaySDK.PLAY_ReleasePort(tempPort);
        }

        sw.Stop();
        _isWarmedUp = true;

        Log.ForContext("SourceContext", LogModules.Core)
            .Debug($"[Dahua] 预热完成！耗时: {sw.ElapsedMilliseconds}ms.");
    }

    #endregion
}