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

namespace MeterVision.FreeAi
{
    public static class DynamicFaImport
    {
        private static readonly object _lock = new object();
        private static IntPtr _hModule;
        private static RecognitionDelegate _recognitionFunc;
        private static bool _isInitialized;

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool FreeLibrary(IntPtr hModule);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        private delegate int RecognitionDelegate(
            [In] short[] rgb565,
            ref FaImport.BeforeAI beforeAI,
            ref FaImport.AfterAI afterAI,
            ref FaImport.SmallImage smallJpg,
            ref FaImport.BigImage bigJpg,
            [MarshalAs(UnmanagedType.LPWStr)] string modelPath,
            FaImport.PrintfCallback callback
        );

        /// <summary>
        /// 初始化并加载 freeAI.dll
        /// </summary>
        /// <param name="dllPath">DLL 文件路径</param>
        /// <returns>是否成功加载</returns>
        public static bool Initialize(string dllPath)
        {
            lock (_lock)
            {
                if (_isInitialized) return true;

                _hModule = LoadLibrary(dllPath);
                if (_hModule == IntPtr.Zero)
                {
                    throw new Exception($"Failed to load DLL: {Marshal.GetLastWin32Error()}");
                }

                IntPtr procAddress = GetProcAddress(_hModule, "recognition");
                if (procAddress == IntPtr.Zero)
                {
                    throw new Exception($"Failed to find function 'recognition': {Marshal.GetLastWin32Error()}");
                }

                _recognitionFunc = Marshal.GetDelegateForFunctionPointer<RecognitionDelegate>(procAddress);
                _isInitialized = true;
                return true;
            }
        }

        /// <summary>
        /// 调用 recognition 函数
        /// </summary>
        /// <param name="rgb565">RGB565 格式的图像数据</param>
        /// <param name="beforeAI">BeforeAI 结构体</param>
        /// <param name="afterAI">AfterAI 结构体</param>
        /// <param name="smallJpg">SmallImage 结构体</param>
        /// <param name="bigJpg">BigImage 结构体</param>
        /// <param name="modelPath">模型文件路径</param>
        /// <param name="callback">回调函数</param>
        /// <returns>返回值</returns>
        public static int Recognition(
            short[] rgb565,
            ref FaImport.BeforeAI beforeAI,
            ref FaImport.AfterAI afterAI,
            ref FaImport.SmallImage smallJpg,
            ref FaImport.BigImage bigJpg,
            string modelPath,
            FaImport.PrintfCallback callback
        )
        {
            if (!_isInitialized)
            {
                throw new InvalidOperationException("The 'recognition' function has not been initialized.");
            }

            return _recognitionFunc(rgb565, ref beforeAI, ref afterAI, ref smallJpg, ref bigJpg, modelPath, callback);
        }

        /// <summary>
        /// 卸载 freeAI.dll
        /// </summary>
        public static void Unload()
        {
            lock (_lock)
            {
                if (_hModule != IntPtr.Zero)
                {
                    FreeLibrary(_hModule);
                    _hModule = IntPtr.Zero;
                    _recognitionFunc = null;
                    _isInitialized = false;
                }
            }
        }
        //--------------------------------------------------------
    }
}
