#include <stdio.h>
#include <string.h>

#include "Drv/pages/YC/page.h"
#include "Drv/pages/YC/model.h"
#include "Drv/pages/YC/presenter.h"
#include "Drv/pages/YC/view.h"
#include "Drv/pages/global/renderer_lcd.h"

/* -------------------------------------------------------------------------
 * 模块内静态对象说明:
 *   s_model     - AppInfo页 Model 实例（AppInfo数据与运行时结构）
 *   s_view      - AppInfo页 View 实例（布局与渲染能力）
 *   s_presenter - AppInfo页 Presenter 实例（输入处理与状态驱动）
 *   s_page  - 页面管理器可注册的 page_t 描述对象
 *
 * 说明:
 *   - 以上对象均为文件内静态单例，生命周期覆盖进程运行期。
 *   - 通过 AppInfoPage_GetInstance() 暴露 s_page 给 PageManager 注册。
 * ------------------------------------------------------------------------- */
static model_t s_model;
static view_t s_view;
static presenter_t s_presenter;
static page_t s_page;
static const PageRenderPort *s_port = NULL;
/* -------------------------------------------------------------------------
 * 函数名: AppInfoPage_OnExit
 * 功能:
 *   页面退出回调占位点；当前版本无额外退出动作。
 *
 * 参数:
 *   page - 当前页面对象指针（本实现未直接使用）
 *
 * 边界处理:
 *   - 使用 (void)page 防止未使用参数告警。
 *
 * 说明:
 *   - 预留给后续扩展（如停止定时任务、冻结动画、保存瞬时 UI 状态等）。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
static void Page_OnExit(page_t *page)
{
    s_port->clear_screen();
    (void)page;
}

/* -------------------------------------------------------------------------
 * 函数名: AppInfoPage_OnDestroy
 * 功能:
 *   页面销毁回调：清空菜单页内部三层对象（Model/View/Presenter）状态。
 *
 * 参数:
 *   page - 当前页面对象指针（本实现未直接使用）
 *
 * 边界处理:
 *   - 使用 memset 全量清零静态对象，避免残留状态影响后续重建。
 *
 * 说明:
 *   - 与 is_cached 策略配合：当页面被标记为非缓存并弹栈销毁时，该函数用于复位。
 *   - page_t 元信息不在此函数复位，由页面生命周期创建阶段重新赋值。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
static void Page_OnDestroy(page_t *page)
{
    (void)page;
    memset(&s_model, 0, sizeof(s_model));
    memset(&s_view, 0, sizeof(s_view));
    memset(&s_presenter, 0, sizeof(s_presenter));
}

/* -------------------------------------------------------------------------
 * 函数名: AppInfoPage_OnEvent
 * 功能:
 *   页面事件回调：校验输入事件后，将按键转交 Presenter 处理。
 *
 * 参数:
 *   page  - 当前页面对象指针（本实现未直接使用）
 *   event - 输入事件指针
 *
 * 边界处理:
 *   - event 为 NULL 时返回 EVENT_UNHANDLED。
 *   - 仅处理 PAGE_EVENT_KEY 事件类型，其它类型返回 EVENT_UNHANDLED。
 *   - keyVal 为 0 视为无效按键，返回 EVENT_UNHANDLED。
 *
 * 说明:
 *   - 事件有效时调用 Presenter 对外输入接口执行业务流转。
 *   - 返回 EVENT_HANDLED，表示该事件已被菜单页消费，不再交给上层页面逻辑。
 *
 * 返回值:
 *   - EVENT_HANDLED   : 事件已处理
 *   - EVENT_UNHANDLED : 事件无效或不属于本页处理范围
 * ------------------------------------------------------------------------- */
static event_result_t Page_OnEvent(page_t *page, input_event_t *event)
{
    (void)page;
    if ((event == NULL) || (event->type != PAGE_EVENT_KEY) || (event->keyVal == 0))
    {
        return EVENT_UNHANDLED;
    }

    s_presenter.handle_input(&s_presenter, event->keyVal);
    return EVENT_HANDLED;
}

/* -------------------------------------------------------------------------
 * 函数名: AppInfoPage_OnLoop
 * 功能:
 *   页面循环回调：周期性驱动 Presenter 执行刷新逻辑。
 *
 * 参数:
 *   page - 当前页面对象指针（本实现未直接使用）
 *
 * 边界处理:
 *   - 使用 (void)page 防止未使用参数告警。
 *
 * 说明:
 *   - 实际刷新策略（全量/增量）由 Presenter 内部状态控制。
 *   - 该函数通常由 PageManager_Loop() 在主循环节拍中调用。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
static void Page_OnLoop(page_t *page)
{
    (void)page;
    s_presenter.refresh(&s_presenter);
}

/* -------------------------------------------------------------------------
 * 函数名: AppInfoPage_OnCreate
 * 功能:
 *   页面创建回调：按 Model -> View -> Presenter 顺序完成菜单页运行时装配，
 *   并初始化 page_t 描述对象字段。
 *
 * 参数:
 *   page - 当前页面对象指针（由 PageManager 传入）
 *
 * 边界处理:
 *   - 先清零 s_menuPage，再统一重建其元信息与回调绑定，避免脏状态遗留。
 *   - 假定 page 非空且来自 PageManager 生命周期调用链。
 *
 * 说明:
 *   - 初始化顺序固定：
 *       1) MenuModel_Init(&s_model)
 *       2) MenuView_Init(&s_view)
 *       3) MenuPresenter_Init(&s_presenter, &s_model, &s_view)
 *   - 将 model/presenter/view 回填到 page 与 s_menuPage，便于调试与统一访问。
 *   - s_menuPage 作为静态页面实例，对外由 MenuPage_GetInstance() 返回。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
static void Page_OnCreate(page_t *page)
{
    /* 1) model init */
    Model_Init(&s_model);

    /* 2) view init */
    View_Init(&s_view);

    /* 3) presenter setup + runtime build */
    Presenter_Init(&s_presenter, &s_model, &s_view);

    
    page->model = &s_model;
    page->presenter = &s_presenter;
    page->view = &s_view;

    s_page.presenter = &s_presenter;
    s_page.view = &s_view;
    s_page.model = &s_model;
    s_port = PageRenderer_Lcd();
}

/* -------------------------------------------------------------------------
 * 函数名: YCPage_OnEnter
 * 功能:
 *   页面进入回调：将菜单渲染标记为“首帧全量刷新”，并立即触发一次刷新。
 *
 * 参数:
 *   page - 当前页面对象指针（本实现未直接使用）
 *
 * 边界处理:
 *   - 本函数不依赖 page 内容，统一转为 (void)page 消除未使用告警。
 *
 * 说明:
 *   - 通过 refresh(..., 1) 告知 Presenter 下一次刷新走首帧路径。
 *   - 进入页面后立即刷新，确保界面可见状态与内部状态同步。
 *
 * 返回值:
 *   - 无
 * ------------------------------------------------------------------------- */
 static void Page_OnEnter(page_t *page)
 {
     (void)page;
     /* 首帧全量刷新 */
     LOG("YCPage_OnEnter\n");
     s_presenter.refresh(&s_presenter);
 }

page_t *YCPage_GetInstance(void)
{
    /* 确保在注册到 PageManager 前，页面生命周期回调已就绪 */
    memset(&s_page, 0, sizeof(s_page));
    s_page.page_id = PAGE_ID_YC;
    s_page.is_cached = 0;
    s_page.on_create = Page_OnCreate;
    s_page.on_enter = Page_OnEnter;
    s_page.on_exit = Page_OnExit;
    s_page.on_destroy = Page_OnDestroy;
    s_page.on_event = Page_OnEvent;
    s_page.on_loop = Page_OnLoop;
    return &s_page;
}
