/**
 * @file    hello_ic.c
 * @brief   hello_ic 教學步驟 1：最小的 Plugin，只在載入時寫一行 Log。
 *
 * 這一步只需要記住三件事：
 *  1. Plugin 是一顆 DLL，Core 只認一個進入點 `NexusPluginGetInterface()`。
 *  2. 進入點回傳一張填好的 `IcPlugin` 表，表裡放名字、位址與 callback。
 *  3. `init()` 是 Plugin 掛載時 Core 呼叫的第一個 callback。
 *
 * @see   docs/NEXUS_TUI_PLUGIN_GUIDE.md 第 1 章 1b、第 2 章
 */

#include "nexus_plugin_api.h"
#include "plugin_version.h"

/**
 * @brief 本 Plugin 對外的名稱。
 * @note  使用者在指令列打 `plugin list` 會看到它，打 `p hello_ic` 就掛載它。
 */
#define HELLO_IC_NAME   "hello_ic"

/**
 * @brief 你的 IC 的 7-bit I2C 位址。
 * @note  **請改成你自己的 IC 的位址。** 不知道位址時，在主程式指令列打 `scan`，
 *        它會列出匯流排上有回應的所有 7-bit 位址。本教學預設 0x58
 *        （模擬後端 mock 預設就有一顆 0x58）。
 */
#define HELLO_IC_ADDR   0x58

/**
 * @brief 本 Plugin 對外宣告的 slave 位址表（至少要有一列，否則 Core 拒載）。
 *
 * @note  欄位依序是：位址、位址模式（8-bit 暫存器位移）、bank 模式（無 bank）、
 *        bank 暫存器、bank 遮罩、旗標、保留、顯示名稱。這一列的意思是
 *        「一顆用 8-bit 暫存器位移定址、沒有 bank 的 IC」，多數 IC 都是這樣。
 * @warning 必須是靜態儲存期：Core 只讀不釋放，所以不能是函式內的區域變數。
 */
static const NxSlaveDecl s_slaves[] =
{
    { HELLO_IC_ADDR, NX_ADDR_MODE_8BIT, NX_BANK_MODE_NONE, 0, 0, 0, { 0, 0 }, "hello_ic" }
};

/**
 * @brief Plugin 掛載時的初始化，Core 在 **UI Thread** 上呼叫。
 *
 * @param[in] ctx  本次掛載的上下文；之後每一次呼叫 HostAPI 都要把它當第一個參數傳回去
 * @param[in] host HostAPI 函式表，生命期涵蓋整個行程；不得修改、不得釋放
 * @return `ERR_OK` 表示成功；非 `ERR_OK` 會使這次掛載中止。
 *
 * @warning 在 UI Thread 上執行，不得做 I2C 存取或任何會阻塞的事。
 * @note    `LogWrite()` 是最簡單的「證明我活著」：這行字會出現在主程式的 Log 面板。
 */
static NxLong NX_CALL hello_ic_init(NxPluginCtx ctx, const NxHostApi *host)
{
    host->LogWrite(ctx, NX_LOG_INFO, "hello_ic: loaded");
    return ERR_OK;
}

/**
 * @brief Plugin 卸載時的清理。**強制實作，不得為 `NULL`。**
 *
 * @param[in] ctx 本次掛載的上下文
 * @return 無
 *
 * @warning 在 **I2C Worker Thread** 上呼叫（不是 UI Thread），返回後 `ctx` 立即失效。
 * @note    步驟 1 沒有任何資源要釋放，所以什麼都不做。
 */
static void NX_CALL hello_ic_cleanup(NxPluginCtx ctx)
{
    NX_UNUSED_ARG(ctx);
}

/**
 * @brief 本 Plugin 的能力宣告，Core 只讀不釋放。
 *
 * @note  必須是靜態儲存期（不能是函式內的區域變數）：靜態變數一開始全是 0，
 *        而 0 對每一個選用 callback 而言正是「我不提供」。
 */
static IcPlugin s_plugin;

/**
 * @brief Plugin DLL 的進入點：Core 載入 DLL 之後第一個呼叫的函式。
 *
 * @param[in] host_abi_major Host 端的 `NX_PLUGIN_ABI_MAJOR`
 * @param[in] host_abi_minor Host 端的 `NX_PLUGIN_ABI_MINOR`（本函式刻意不比較：minor 不同不是拒載的理由）
 * @return 指向靜態生命期 `IcPlugin` 的指標；ABI major 不相容時回傳 `NULL`。
 *
 * @warning 在 UI Thread 上呼叫，不得做 I2C 存取或阻塞操作。
 * @note    欄位一律用**具名賦值**填寫，沒填的欄位維持 0（＝不提供該 callback）。
 */
NX_PLUGIN_EXPORT struct IcPlugin * NX_CALL NexusPluginGetInterface(NxDword host_abi_major,
                                                                   NxDword host_abi_minor)
{
    NX_UNUSED_ARG(host_abi_minor);

    if (host_abi_major != NX_PLUGIN_ABI_MAJOR)
    {
        return (struct IcPlugin *)0;
    }

    s_plugin.abi_major       = NX_PLUGIN_ABI_MAJOR;
    s_plugin.abi_minor       = NX_PLUGIN_ABI_MINOR;
    s_plugin.size_of_struct  = sizeof(IcPlugin);

    s_plugin.name            = HELLO_IC_NAME;
    s_plugin.description     = "hello_ic tutorial plugin";

    s_plugin.slaves          = s_slaves;
    s_plugin.slave_count     = (NxByte)(sizeof(s_slaves) / sizeof(s_slaves[0]));
    s_plugin.slave_decl_size = (NxDword)sizeof(NxSlaveDecl);
    s_plugin.panel_mode      = NX_PANEL_MODE_NONE;

    s_plugin.init            = hello_ic_init;
    s_plugin.cleanup         = hello_ic_cleanup;

    s_plugin.version_major   = (NxWord)PLUGIN_VER_MAJOR;
    s_plugin.version_minor   = (NxWord)PLUGIN_VER_MINOR;
    s_plugin.version_patch   = (NxWord)PLUGIN_VER_PATCH;

    return &s_plugin;
}
