#include <string.h>

#include "global_state.h"

static GlobalModel s_globalModel;

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_CopyText
 * 功能:
 *   安全地将源字符串拷贝到目标缓冲区，确保不会发生缓冲区溢出。
 *
 * 参数:
 *   dst    - 目标缓冲区指针（输出），用于存放拷贝的字符串
 *   dstSize - 目标缓冲区的大小（字节）
 *   src    - 源字符串指针（输入），需要被拷贝的字符串
 *
 * 边界处理:
 *   - 若 dst 为 NULL 或 dstSize 为 0，函数直接返回，不做任何操作。
 *   - 若 src 为 NULL，则将目标缓冲区置为空字符串 (dst[0] = '\0')。
 *   - 拷贝时最多保留 dstSize-1 个字符，确保最后一个字节用于存放字符串结束符 '\0'。
 *   - 若在拷贝过程中遇到源字符串的结束符 '\0'，则提前终止拷贝。
 *
 * 说明:
 *   - 本函数是一个安全的字符串拷贝工具，专门用于全局模型中菜单名称和提示文本的拷贝。
 *   - 通过限制拷贝长度为 dstSize-1 并强制在末尾添加 '\0'，确保目标缓冲区永远不会越界。
 *   - 当源字符串长度大于等于目标缓冲区大小时，会截断源字符串，但保证结果仍是有效的 C 字符串。
 *   - 该函数为静态函数，仅在当前文件内部使用。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
static void GlobalModel_CopyText(uint8_t *dst, uint16_t dstSize, const uint8_t *src)
{
    uint16_t i;
    if ((dst == NULL) || (dstSize == 0))
    {
        return;
    }

    if (src == NULL)
    {
        dst[0] = '\0';
        return;
    }

    for (i = 0; i < (uint16_t)(dstSize - 1); i++)
    {
        dst[i] = src[i];
        if (src[i] == '\0')
        {
            return;
        }
    }
    dst[dstSize - 1] = '\0';
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_Init
 * 功能:
 *   初始化全局模型实例，将所有成员变量设置为零值。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不处理任何异常情况，直接对静态全局变量进行清零操作。
 *
 * 说明:
 *   - 本函数用于在系统启动或需要重置全局状态时调用。
 *   - 通过 memset 将 s_globalModel 的所有字节设置为 0，包括：
 *       1) activeYcType（当前遥测类型）
 *       2) activeMenuPara（当前菜单参数）
 *       3) activeActionId（当前菜单动作 ID）
 *       4) activeMenuName（当前菜单名称数组）
 *       5) activeMenuTip（当前菜单提示文本数组）
 *   - 初始化后，全局模型处于空状态，需要调用其他设置函数来配置有效值。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
void GlobalModel_Init(void)
{
    memset(&s_globalModel, 0, sizeof(s_globalModel));
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_Instance
 * 功能:
 *   获取全局模型单例实例的指针，用于访问和修改全局状态数据。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不做任何校验，始终返回静态变量 s_globalModel 的地址。
 *   - 调用方应确保在调用此函数前已先调用 GlobalModel_Init() 进行初始化。
 *
 * 说明:
 *   - 本函数采用单例模式，提供对全局模型实例的访问接口。
 *   - 返回的是静态变量 s_globalModel 的指针，该变量在整个程序生命周期内只有一份副本。
 *   - 调用方可以通过返回的指针直接访问和修改全局状态成员，如 activeYcType、activeActionId 等。
 *   - 由于返回的是原始指针，调用方在操作时应注意线程安全和数据一致性。
 *
 * 返回值:
 *   - 指向 GlobalModel 结构体的指针
 * ------------------------------------------------------------------------- */
GlobalModel *GlobalModel_Instance(void)
{
    return &s_globalModel;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_SetActiveYcType
 * 功能:
 *   设置当前活跃的遥测类型，用于标识系统正在处理哪种类型的遥测量。
 *
 * 参数:
 *   ycType - 遥测类型值，通常为枚举类型或预定义的类型常量
 *
 * 边界处理:
 *   - 本函数不做参数合法性校验，调用方应保证 ycType 为有效值。
 *
 * 说明:
 *   - 该函数用于设置全局模型中的 activeYcType 字段。
 *   - 遥测类型用于区分不同类型的交流量（如电压、电流、功率等）。
 *   - 设置后，系统其他模块可通过 GetActiveYcType() 查询当前类型。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
void GlobalModel_SetActiveYcType(uint16_t ycType)
{
    s_globalModel.activeYcType = ycType;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetActiveYcType
 * 功能:
 *   获取当前活跃的遥测类型。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不做任何校验，直接返回静态变量的值。
 *   - 若系统未初始化或类型未被设置，可能返回 0（默认值）。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeYcType 字段。
 *   - 返回值表示当前系统正在处理或最后设置的遥测类型。
 *   - 调用方应根据返回的值进行相应的数据处理或界面显示逻辑。
 *
 * 返回值:
 *   - 当前活跃的遥测类型值
 * ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetActiveYcType(void)
{
    return s_globalModel.activeYcType;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_SetMenuAction
 * 功能:
 *   设置当前菜单的动作信息，包括动作 ID、名称、提示文本和参数。
 *
 * 参数:
 *   actionId - 菜单动作 ID，用于标识具体的菜单操作（如查看、设置等）
 *   menuName - 菜单名称字符串，显示在界面上的菜单标题
 *   menuTip  - 菜单提示文本字符串，用于显示辅助说明信息
 *   menuPara - 菜单参数，传递与当前菜单相关的额外数据
 *
 * 边界处理:
 *   - 若 menuName 或 menuTip 为 NULL，对应缓冲区将被置为空字符串。
 *   - 名称和提示文本的长度会被限制在各自缓冲区大小内（50 字节），超长部分会被截断。
 *   - 本函数不做输入参数的合法性校验，调用方应保证 actionId/menuPara 为有效值。
 *
 * 说明:
 *   - 该函数用于更新全局模型中的菜单动作相关信息。
 *   - 通过 GlobalModel_CopyText() 进行安全拷贝，确保不会发生缓冲区溢出。
 *   - 设置后，系统其他模块可通过对应的 Get 系列函数查询当前菜单状态。
 *   - 此函数通常在进入新菜单或切换菜单时调用，用于更新全局上下文信息。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
void GlobalModel_SetMenuAction(uint16_t activeAttrib,
                               const uint8_t *menuName,
                               const uint8_t *menuTip,
                               uint16_t menuPara)
{
    s_globalModel.activeAttrib = activeAttrib;
    s_globalModel.activeMenuPara = menuPara;
    GlobalModel_CopyText(s_globalModel.activeMenuName,
                         (uint16_t)sizeof(s_globalModel.activeMenuName),
                         menuName);
    GlobalModel_CopyText(s_globalModel.activeMenuTip,
                         (uint16_t)sizeof(s_globalModel.activeMenuTip),
                         menuTip);
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetMenuActionId
 * 功能:
 *   获取当前菜单的动作 ID。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不做任何校验，直接返回静态变量的值。
 *   - 若未调用 SetMenuAction() 设置，将返回默认值 0。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeActionId 字段。
 *   - 返回值表示当前菜单对应的动作类型，可用于判断用户当前所处的菜单位置。
 *
 * 返回值:
 *   - 当前菜单的动作 ID（menu_action_id_t 枚举值）
 * ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetMenuActionId(void)
{
    return s_globalModel.activeActionId;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetMenuActionPara
 * 功能:
 *   获取当前菜单的参数值。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不做任何校验，直接返回静态变量的值。
 *   - 若未调用 SetMenuAction() 设置，将返回默认值 0。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeMenuPara 字段。
 *   - 返回值是与当前菜单相关的额外参数数据，具体含义取决于菜单类型。
 *
 * 返回值:
 *   - 当前菜单的参数值
 * ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetMenuActionPara(void)
{
    return s_globalModel.activeMenuPara;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetMenuActionName
 * 功能:
 *   获取当前菜单的名称字符串。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数返回静态缓冲区的指针，调用方不应修改返回的字符串内容。
 *   - 若未调用 SetMenuAction() 设置，将返回空字符串指针（内容为 "\0"）。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeMenuName 缓冲区。
 *   - 返回的是 const 指针，表明调用方只能读取不能修改该字符串。
 *   - 字符串长度最多为 49 个字符（预留 1 字节给结束符 '\0'）。
 *
 * 返回值:
 *   - 指向当前菜单名称字符串的常量指针
 * ------------------------------------------------------------------------- */
const uint8_t *GlobalModel_GetMenuActionName(void)
{
    return s_globalModel.activeMenuName;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetMenuActionTip
 * 功能:
 *   获取当前菜单的提示文本字符串。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数返回静态缓冲区的指针，调用方不应修改返回的字符串内容。
 *   - 若未调用 SetMenuAction() 设置，将返回空字符串指针（内容为 "\0"）。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeMenuTip 缓冲区。
 *   - 返回的是 const 指针，表明调用方只能读取不能修改该字符串。
 *   - 字符串长度最多为 49 个字符（预留 1 字节给结束符 '\0'）。
 *
 * 返回值:
 *   - 指向当前菜单提示文本字符串的常量指针
 * ------------------------------------------------------------------------- */
const uint8_t *GlobalModel_GetMenuActionTip(void)
{
    return s_globalModel.activeMenuTip;
}

/* -------------------------------------------------------------------------
 * 函数名：GlobalModel_GetMenuActionAttrib
 * 功能:
 *   获取当前菜单的动作属性。
 *
 * 参数:
 *   无
 *
 * 边界处理:
 *   - 本函数不做任何校验，直接返回静态变量的值。
 *   - 若未调用 SetMenuAction() 设置，将返回默认值 0。
 *
 * 说明:
 *   - 该函数用于查询全局模型中的 activeAttrib 字段。
 *   - 返回值是与当前菜单相关的动作属性，具体含义取决于动作类型。
 *
 * 返回值:
 *   - 当前菜单的动作属性
 * ------------------------------------------------------------------------- */
 uint16_t GlobalModel_GetMenuActionAttrib(void)
 {
     return s_globalModel.activeAttrib;
 }
