/* ============================================================
   P 项目 — wrapper.cpp
   封装层实现 — 通过 LoadLibrary 调用现有 DLL 的导出函数

   不需要 SDK 头文件！不需要 .lib 文件！
   直接用 LoadLibrary + GetProcAddress 动态加载 DLL

   编译环境: Windows x64, Visual Studio 2019+
   运行时依赖: 将下面三个 DLL 放在 wrapper.dll 同目录:
     - ICDevice.dll     (加密狗)
     - TwoEyeApi.dll    (双目相机核心 API)
     - TwoEyeApiEx.dll  (扩展接口)

   使用方法:
     1. Visual Studio 新建 "动态链接库(DLL)" 项目
     2. 添加本文件 + wrapper.h
     3. 不需要链接任何 .lib
     4. 编译 → 出 wrapper.dll
   ============================================================ */

#include "wrapper.h"
#include <windows.h>    // LoadLibrary, GetProcAddress
#include <cstring>      // memset, memcpy

/* ───── DLL 模块句柄 ───── */
static HMODULE g_hIcDevice   = NULL;  // ICDevice.dll
static HMODULE g_hTwoEyeApi  = NULL;  // TwoEyeApi.dll

/* ───── 全局状态 ───── */
static int g_dongle_opened  = 0;
static int g_camera_inited  = 0;

/* ============================================================
   加载所有 DLL
   ============================================================ */
static int LoadSDKDLLs(void)
{
    if (!g_hIcDevice) {
        g_hIcDevice = LoadLibraryA("ICDevice.dll");
        if (!g_hIcDevice) return -1;
    }
    if (!g_hTwoEyeApi) {
        g_hTwoEyeApi = LoadLibraryA("TwoEyeApi.dll");
        if (!g_hTwoEyeApi) return -2;
    }
    return 0;
}

/* ============================================================
   卸载所有 DLL
   ============================================================ */
static void UnloadSDKDLLs(void)
{
    if (g_hTwoEyeApi) { FreeLibrary(g_hTwoEyeApi); g_hTwoEyeApi = NULL; }
    if (g_hIcDevice)  { FreeLibrary(g_hIcDevice);  g_hIcDevice  = NULL; }
}

/* ============================================================
   1. IC_Open — 打开加密狗 (ICDevice.dll)
   ============================================================ */
__declspec(dllexport) int IC_Open(void)
{
    // ──────────────────────────────────────
    // TODO: 程序员填写
    //
    // 从 ICDevice.dll 找到加密狗初始化函数并调用
    //
    // 参考步骤:
    //   1. 如果 g_hIcDevice 为空，先 LoadLibrary
    //   2. 用 GetProcAddress 获取函数地址
    //   3. 调用，判断返回值
    //
    // 在 Windows 命令提示符中运行以下命令可查看 DLL 中的所有导出函数:
    //   dumpbin /exports ICDevice.dll
    //
    // 示例代码（函数名和参数类型请根据实际修改）:
    //
    //   typedef int (*IC_Start_t)();
    //   auto IC_Start = (IC_Start_t)GetProcAddress(g_hIcDevice, "IC_Start");
    //   if (!IC_Start) return -101;
    //   int ret = IC_Start();
    //   if (ret == 0) { g_dongle_opened = 1; return 0; }
    //   return ret;
    // ──────────────────────────────────────

    if (LoadSDKDLLs() != 0) return -1;

    // 在这里用 GetProcAddress 获取并调用函数
    // TODO: 程序员填写

    g_dongle_opened = 1;
    return 0;
}

/* ============================================================
   2. IC_Close — 关闭加密狗
   ============================================================ */
__declspec(dllexport) void IC_Close(void)
{
    // TODO: 获取 ICDevice.dll 中的关闭函数并调用
    // 例如:
    //   typedef void (*IC_Stop_t)();
    //   auto IC_Stop = (IC_Stop_t)GetProcAddress(g_hIcDevice, "IC_Stop");
    //   if (IC_Stop) IC_Stop();

    g_dongle_opened = 0;
}

/* ============================================================
   3. Camera_Init — 初始化双目相机 (TwoEyeApi.dll)
   ============================================================ */
__declspec(dllexport) int Camera_Init(void)
{
    if (!g_dongle_opened) return -100;

    // ──────────────────────────────────────
    // TODO: 程序员填写
    //
    // 从 TwoEyeApi.dll 中找到初始化函数并调用
    // 用 dumpbin /exports TwoEyeApi.dll 查看所有导出函数
    //
    // 可能是:
    //   InitUseCam2011()  — 初始化双目相机
    //   或其他命名
    // ──────────────────────────────────────

    // 在这里用 GetProcAddress 获取并调用函数
    // TODO: 程序员填写

    g_camera_inited = 1;
    return 0;
}

/* ============================================================
   4. Camera_Capture — 采集一帧
   ============================================================ */
__declspec(dllexport) int Camera_Capture(
    unsigned char* left_buf,
    unsigned char* right_buf,
    int*           width,
    int*           height
)
{
    if (!g_camera_inited) return -200;
    if (!left_buf || !right_buf || !width || !height) return -300;

    // ──────────────────────────────────────
    // TODO: 程序员填写
    //
    // 调用 TwoEyeApi.dll 中的采集函数
    // 将左右相机数据分别拷贝到 left_buf 和 right_buf
    // 设置 *width 和 *height 为实际分辨率
    //
    // 图像参数:
    //   最高分辨率: 1280 × 1024
    //   连续扫描:  640 × 512（灰度图）
    //   格式: 8bit 灰度（请确认）
    //
    // 提示: 可先填固定值 1280×1024 调试
    //   先用 memset 填 0 或纯色数据测试链路通不通
    // ──────────────────────────────────────

    *width  = 1280;
    *height = 1024;

    // TODO: 从相机 API 获取真实数据并填入缓冲区
    //   例如:
    //   typedef int (*CaptureFn_t)(unsigned char*, unsigned char*, int*, int*);
    //   auto fn = (CaptureFn_t)GetProcAddress(g_hTwoEyeApi, "函数名");
    //   return fn(left_buf, right_buf, width, height);

    return 0;
}

/* ============================================================
   5. Camera_Close — 关闭相机
   ============================================================ */
__declspec(dllexport) void Camera_Close(void)
{
    // TODO: 调用 TwoEyeApi.dll 中的关闭函数

    g_camera_inited = 0;
}
