/**
 * @file hv_app_Osd.c
 * @brief osd app operation c file.
 * @details This file provides the following functions: \n
 *          (1) Osd operation functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-09-01
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                      <th>Date            <th>Change Description
 * <tr><td>HiView SoC Software Team    <td>2022-09-01      <td>create
 * </table>
 */

#include <stdio.h>
#include "hv_comm_DataBase.h"
#include "hv_mw_OsdComm.h"
#include "hv_mw_OsdLog.h"
#include "hv_mw_OsdDraw.h"
#include "hv_mw_OsdEvent.h"
#include "hv_mw_OsdOperation.h"
#include "hv_app_PQ.h"
#include "hv_app_Osd.h"
#include "hv_app_OsdDialog.h"
#include "hv_app_OsdFactory.h"
#include "hv_app_OsdMenu.h"

typedef struct _OsdFunctionTable
{
    USHORT16    usEventId;
    VOID      (*pfOsdFunction)(USHORT16 usValue);
} OsdFunctionTable;

OsdRotationType Hv_App_OsdGetRotateType(VOID)
{
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_OSD_ROTATION)
    return HV_COMMON_DATABASE_GET(UserData, ucOsdRotation);
#else
    return 0;
#endif
}

VOID Hv_App_OsdSetRotateType(OsdRotationType enRotate)
{
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_OSD_ROTATION)
    HV_COMMON_DATABASE_SET(UserData, ucOsdRotation, enRotate);
    Hv_Mw_OsdSetRotateType(enRotate);
    Hv_Mw_OsdOpsForceRedraw(HV_TRUE);
#endif
}

OsdLanguage Hv_App_OsdGetLanguage(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdLanguage);
}

VOID Hv_App_OsdSetLanguage(OsdLanguage enLang)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdLanguage, enLang);
    Hv_Mw_OsdSetLanguage(enLang);
    Hv_Mw_OsdOpsForceRedraw(HV_TRUE);
}

USHORT16 Hv_App_OsdGetMenuTime(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdTime);
}

VOID Hv_App_OsdSetMenuTime(USHORT16 usTimeType)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdTime, usTimeType);
}

USHORT16 Hv_App_OsdGetTrans(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdTrans);
}

VOID Hv_App_OsdSetTrans(USHORT16 usTrans)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdTrans, usTrans);
    Hv_Mw_OsdSetTransparency(usTrans);
}

BOOL Hv_App_OsdGetLock(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdLock);
}

VOID Hv_App_OsdSetLock(BOOL bLock)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdLock, bLock);
}

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_CROSSHAIR)
USHORT16 Hv_App_OsdGetCrosshair(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdCrosshair);
}

VOID Hv_App_OsdSetCrosshair(USHORT16 usType)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdCrosshair, usType);
}

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_AMBILIGHT)
USHORT16 Hv_App_OsdGetDynCrosshair(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucDynCrosshair);
}

VOID Hv_App_OsdSetDynCrosshair(USHORT16 usType)
{
    HV_COMMON_DATABASE_SET(UserData, ucDynCrosshair, usType);

    if (HV_TRUE == usType)
    {
        OsdScene *pstSceneCrossHair = OSD_GET_SCENE(SCENE_CROSSHAIR);
        CrosshairArea stArea = {pstSceneCrossHair->usX,
                                pstSceneCrossHair->usY,
                                pstSceneCrossHair->usWidth,
                                pstSceneCrossHair->usHeight};
        Hv_App_PQ_CrosshairInit();
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_OSD_SCALER)
        stArea.usX *= 2;
        stArea.usY *= 2;
#endif
        Hv_App_PQ_CrosshairSetArea(&stArea);
    }
    Hv_App_PQ_CrosshairEnable(usType);
}
#endif
#endif

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_REFRESH_RATE)
USHORT16 Hv_App_OsdGetFrameRateShow(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdFrameCounter);
}

VOID Hv_App_OsdSetFrameRateShow(USHORT16 usType)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdFrameCounter, usType);
}
#endif

USHORT16 Hv_App_OsdGetTimerCounterShow(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucOsdTimerCounter);
}

VOID Hv_App_OsdSetTimerCounterShow(USHORT16 usType)
{
    HV_COMMON_DATABASE_SET(UserData, ucOsdTimerCounter, usType);
}

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_CUSTOM_KEY)
USHORT16 Hv_App_OsdGetCustomKey(USHORT16 usKey)
{
    if (1 == usKey)
    {
        return HV_COMMON_DATABASE_GET(UserData, ucOsdCustomKey1);
    }
    else if (2 == usKey)
    {
        return HV_COMMON_DATABASE_GET(UserData, ucOsdCustomKey2);
    }
    else if (3 == usKey)
    {
        return HV_COMMON_DATABASE_GET(UserData, ucOsdCustomKey3);
    }
	else
	{
	    return 0;
	}
}

VOID Hv_App_OsdSetCustomKey(USHORT16 usKey, USHORT16 usType)
{
    if (1 == usKey)
    {
        HV_COMMON_DATABASE_SET(UserData, ucOsdCustomKey1, usType);
    }
    else if (2 == usKey)
    {
        HV_COMMON_DATABASE_SET(UserData, ucOsdCustomKey2, usType);
    }
    else if (3 == usKey)
    {
        HV_COMMON_DATABASE_SET(UserData, ucOsdCustomKey3, usType);
    }
}
#endif

USHORT16 Hv_App_OsdGetMenuPostion(BOOL bIsX)
{
    if (bIsX)
    {
        return HV_COMMON_DATABASE_GET(UserData, ucOsdMenuHPos);
    }
    else
    {
        return HV_COMMON_DATABASE_GET(UserData, ucOsdMenuVPos);
    }
}

/* Add position-movable scene here */
VOID Hv_App_OsdSetMenuPostion(BOOL bIsX, USHORT16 usRatio)
{
    USHORT16 usFullWidth = 0;
    USHORT16 usFullHeight = 0;
    USHORT16 usLimitPosStart = 0;
    USHORT16 usLimitPosEnd = INVALID_PARAM_USHORT16;

    Hv_Mw_OsdGetDisplaySize(&usFullWidth, &usFullHeight);
    if (bIsX)
    {
        usLimitPosStart = 30;
        usLimitPosEnd = usFullWidth - 30;
    }
    else
    {
        usLimitPosStart = 30;
        usLimitPosEnd = usFullHeight - 30;
    }

    if (bIsX)
    {
        HV_COMMON_DATABASE_SET(UserData, ucOsdMenuHPos, usRatio);
    }
    else
    {
        HV_COMMON_DATABASE_SET(UserData, ucOsdMenuVPos, usRatio);
    }

    
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_CONTRAST, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_RESET_ALL, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_POWER_TIPS, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_FUNCTION_TIPS, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_BRIGHTNESS, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_VOLUME, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_MODE, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_INPUT, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_LOCK, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_MAIN, bIsX, usRatio, usLimitPosStart, usLimitPosEnd);

#if (HV_PROJECT_CONFIG_OSD_ROTATION == HV_CONFIG_ON)
    if (UD_ROTATION_V_OFF != Hv_App_GetOsdDataValue(E_USERDATA_ROTATION))
    {
        Hv_Mw_OsdOpsForceRedraw(HV_TRUE);
    }
#endif
}

/* Add position-static scene here */
static VOID SceneStaticPostionInit(VOID)
{
    USHORT16 usLimitPosStart = 0;
    USHORT16 usLimitPosEnd = INVALID_PARAM_USHORT16;

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_INPUT_SOURCE, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_INPUT_SOURCE, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_INPUT_SOURCE_SUB, HV_TRUE, 1, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_INPUT_SOURCE_SUB, HV_FALSE, 99, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_NOSIGNAL, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_NOSIGNAL, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_SIGNAL_UNSUPPORT, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_SIGNAL_UNSUPPORT, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_FUNCTION_UNSUPPORT, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_FUNCTION_UNSUPPORT, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_CROSSHAIR, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_CROSSHAIR, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetRotateSkip(SCENE_CROSSHAIR, HV_TRUE);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_REFRESH_RATE, HV_TRUE, 1, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_REFRESH_RATE, HV_FALSE, 99, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_TIMER, HV_TRUE, 99, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_TIMER, HV_FALSE, 99, 0, INVALID_PARAM_USHORT16);

    Hv_Mw_OsdSceneSetPositionRatio(SCENE_OTA, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_OTA, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);

#if (HV_PROJECT_CONFIG_OSD_LOGO_USE_SCENE == HV_CONFIG_ON)
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_LOGO, HV_TRUE, 50, 0, INVALID_PARAM_USHORT16);
    Hv_Mw_OsdSceneSetPositionRatio(SCENE_LOGO, HV_FALSE, 50, 0, INVALID_PARAM_USHORT16);
#endif
}

VOID Hv_App_Cb_OsdInit(VOID)
{
    OSD_LOG_DEBUG("Osd app init");

    /* 初始化所有Userdata相关设置 */
    Hv_App_InitToUserSetting();

    /* 初始化所有静态scene的位置 */
    SceneStaticPostionInit();

    /* set ENTER key holdable */
    Hv_Mw_OsdSetKeyState(OSDEVT_KEY_ENTER, KEY_STATE_HOLDABLE, HV_TRUE);
}

USHORT16 Hv_App_OsdSetFirmwareVersionString(UCHAR8 *pucString)
{
    UCHAR8 aucDate[] = "20241209";
    USHORT16 usLen = 0;

    UCHAR8 *apucMonths[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    SHORT16 sMonth;
    for (sMonth = 0; sMonth < 12; sMonth++) {
        if (strncmp(aucDate, apucMonths[sMonth], 3) == 0) {
            break;
        }
    }

    SHORT16 sDay = 0;
    SHORT16 sYear = 0;
    UCHAR8 *pucToken = strtok(aucDate + 4, " ");
    if (pucToken != NULL) {
        sDay = atoi(pucToken);
    }
    pucToken = strtok(NULL, " ");
    if (pucToken != NULL) {
        sYear = atoi(pucToken);
    }
    UCHAR8 ucYear = (sYear - 2023) + 'N';
    usLen = HV_SNPRINTF(pucString, OSD_ASCII_STRING_LENGTH_MAX, "HIVIEW.%c%02d%02d", ucYear, sMonth + 1, sDay);
    OSD_LOG_DEBUG("FW String: %s", pucString);
    return usLen;
}

USHORT16 Hv_App_OsdSetTimingInfoString(UCHAR8 *pstString, USHORT16 usH, USHORT16 usV, USHORT16 usHz, BOOL bIsVrr, BOOL bInterlacedMode)
{
    if (!bInterlacedMode)
    {
        if (bIsVrr)
        {
            return (pstString == NULL) ? 0 : HV_SNPRINTF(pstString, OSD_ASCII_STRING_LENGTH_MAX, "%dx%d@VRR", usH, usV);
        }
        else
        {
            return (pstString == NULL) ? 0 : HV_SNPRINTF(pstString, OSD_ASCII_STRING_LENGTH_MAX, "%dx%d@%dHz", usH, usV, usHz);
        }
    }
    else
    {
        if (bIsVrr)
        {
            return (pstString == NULL) ? 0 : HV_SNPRINTF(pstString, OSD_ASCII_STRING_LENGTH_MAX, "%dx%dI@VRR", usH, usV);
        }
        else
        {
            return (pstString == NULL) ? 0 : HV_SNPRINTF(pstString, OSD_ASCII_STRING_LENGTH_MAX, "%dx%dI@%dHz", usH, usV, usHz);
        }
    }
}

static VOID Hv_App_OsdRecoverPreviewSetting(UserdataId enUserdata)
{
    if (Hv_App_OsdGetNeedConfirmAdjusting())
    {
        SHORT16 sUserdataBackupValue = Hv_App_OsdGetNeedConfirmBackupValue();
        Hv_Mw_OsdAdjustFunction(enUserdata, ACT_SET, sUserdataBackupValue, SET_OSDDATA);
        Hv_App_OsdSetNeedConfirmAdjusting(HV_FALSE);
    }
}

VOID Hv_App_OsdHideAll(VOID)
{
    USHORT16 usCurFocusing = OSD_GET_FOCUSING();
    if (usCurFocusing != ITEM_NONE_ID)
    {
        UserdataId enUserdata = OSD_GET_USERDATA(usCurFocusing);
        Hv_App_OsdRecoverPreviewSetting(enUserdata);
    }

    Hv_Mw_OsdSceneClearAll();
}

VOID Hv_App_OsdHideAllProc(USHORT16 usValue)
{
    Hv_App_OsdHideAll();

    if (1 == usValue)
    {
        /* 禁用所有按键 */
        Hv_Mw_OsdSetAllKeyEnable(HV_FALSE);
    }
}

static VOID Hv_App_OsdKeyHoldProc(USHORT16 usValue)
{
    switch (Hv_Mw_OsdGetHoldKey())
    {
        case OSDEVT_KEY_ENTER:
        {
            if (UD_MENULOCK_V_ON == Hv_App_GetOsdDataValue(E_USERDATA_MENULOCK))
            {
                Hv_Mw_OsdAdjustFunction(E_USERDATA_MENULOCK, ACT_SET, UD_MENULOCK_V_OFF, SET_ALL);
                Hv_App_OsdLockEnter(HV_FALSE);
            }
            break;
        }
        default:
        {
            break;
        }
    }
}

static VOID Hv_App_OsdAutoClose(USHORT16 usValue)
{
    OSD_LOG_DEBUG("Auto close Scene-%d", usValue);
    switch (usValue)
    {
        case SCENE_INPUT_SOURCE:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_INPUT_SOURCE))
            {
                Hv_App_OsdSourcePlugInExit();
            }
            break;
        }
        case SCENE_INPUT_SOURCE_SUB:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_INPUT_SOURCE_SUB))
            {
                Hv_App_OsdSubSourcePlugInExit();
            }
            break;
        }
        case SCENE_NOSIGNAL:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_NOSIGNAL))
            {
                Hv_App_OsdNoSignalExit();
            }
            break;
        }
        case SCENE_SIGNAL_UNSUPPORT:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_SIGNAL_UNSUPPORT))
            {
                Hv_App_OsdSignalUnsupportExit();
            }
            break;
        }
        case SCENE_FUNCTION_UNSUPPORT:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_FUNCTION_UNSUPPORT))
            {
                Hv_App_OsdFunctionUnsupportExit();
            }
            break;
        }
        case SCENE_LOCK:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_LOCK))
            {
                Hv_App_OsdLockExit();
            }
            break;
        }
        case SCENE_MAIN:
        {
            USHORT16 usCurFocusing = OSD_GET_FOCUSING();
            if (usCurFocusing != ITEM_NONE_ID)
            {
                USHORT16 usCurScene = ITEM_GET_SCENEID(usCurFocusing);
                UserdataId enUserdata = OSD_GET_USERDATA(usCurFocusing);
                Hv_App_OsdRecoverPreviewSetting(enUserdata);
                Hv_Mw_OsdItemFocusClear();
                Hv_Mw_OsdSceneHide(usCurScene);
                Hv_Mw_OsdSceneClear(usCurScene);
            }
            break;
        }
        case SCENE_OTA:
        {
            if (Hv_Mw_OsdSceneIsShowing(SCENE_OTA))
            {
                Hv_App_OsdOtaExit();
            }
            break;
        }
        default:
        {
            break;
        }
    }
    return;
}

static VOID Hv_App_OsdAutoRefresh(USHORT16 usValue)
{
    OSD_LOG_DEBUG("Auto refresh Scene-%d", usValue);

    switch (usValue)
    {
        case SCENE_REFRESH_RATE:
            Hv_App_OsdRefreshRateUpdate();
            break;
        case SCENE_TIMER:
            Hv_App_OsdTimeCounterUpdate();
            break;
        case SCENE_CROSSHAIR:
            Hv_App_OsdCrosshairUpdate();
            break;
        case SCENE_MAIN:
            Hv_App_OsdMainMenuUpdate();
            break;
        case SCENE_INPUT_SOURCE:
            Hv_App_OsdSourcePlugInUpdate();
            break;
        default:
            break;
    }
}

static BOOL Hv_App_OsdIsShowingExcept(VOID)
{
    for (USHORT16 usId = 0; usId < SCENE_ID_MAX; usId++)
    {
        if ((SCENE_CROSSHAIR == usId) || (SCENE_REFRESH_RATE == usId) || (SCENE_TIMER == usId))
        {
            OSD_LOG_DEBUG("Except Scene-%d", usId);
            continue;
        }

        if (Hv_Mw_OsdSceneIsShowing(usId))
        {
            OSD_LOG_DEBUG("Scene-%d is showing", usId);
            return HV_TRUE;
        }
    }

    OSD_LOG_DEBUG("No Scene is showing");
    return HV_FALSE;
}

static VOID Hv_App_OsdFactoryEnter(USHORT16 usValue)
{
    OSD_LOG_DEBUG("Enter Factory Mode");
    HV_COMMON_DATABASE_SET(SystemData, bFactoryMode, HV_TRUE);
    Hv_App_OsdHideAll();
}

static VOID Hv_App_OsdFactoryExit(USHORT16 usValue)
{
    OSD_LOG_DEBUG("Exit Factory Mode");
    HV_COMMON_DATABASE_SET(SystemData, bFactoryMode, HV_FALSE);
    Hv_App_OsdHideAll();
}

static VOID Hv_App_OsdCheckAutoShow(VOID)
{
    OsdTimingInfo *pstTiming = Hv_App_OsdGetCurrentTimingInfo();
    BOOL bSignalSync = pstTiming ? (pstTiming->bSignalSync || pstTiming->bSubSignalSync) : HV_FALSE;

    /* Crosshair check */
    if (UD_CROSSHAIR_V_NONE != Hv_App_GetOsdDataValue(E_USERDATA_CROSSHAIR))
    {
        if ((!Hv_App_OsdIsShowingExcept()) && (bSignalSync))
        {
            if (!Hv_Mw_OsdSceneIsShowing(SCENE_CROSSHAIR))
            {
                Hv_App_OsdCrosshairEnter();
            }
        }
        else if (Hv_Mw_OsdSceneIsShowing(SCENE_CROSSHAIR))
        {
            Hv_App_OsdCrosshairExit();
        }
    }
    else if (Hv_Mw_OsdSceneIsShowing(SCENE_CROSSHAIR))
    {
        Hv_App_OsdCrosshairExit();
    }

    /* RefreshRate check */
    if (UD_REFRESH_RATE_V_OFF != Hv_App_GetOsdDataValue(E_USERDATA_REFRESH_RATE))
    {
        if ((!Hv_App_OsdIsShowingExcept()) && (bSignalSync))
        {
            if (!Hv_Mw_OsdSceneIsShowing(SCENE_REFRESH_RATE))
            {
                Hv_App_OsdRefreshRateEnter();
            }
        }
        else if (Hv_Mw_OsdSceneIsShowing(SCENE_REFRESH_RATE))
        {
            Hv_App_OsdRefreshRateExit();
        }
    }
    else if (Hv_Mw_OsdSceneIsShowing(SCENE_REFRESH_RATE))
    {
        Hv_App_OsdRefreshRateExit();
    }

    /* TimerCounter check */
    if (UD_TIME_COUNTER_V_OFF != Hv_App_GetOsdDataValue(E_USERDATA_TIME_COUNTER))
    {
        if ((!Hv_App_OsdIsShowingExcept()) && (bSignalSync))
        {
            if (!Hv_Mw_OsdSceneIsShowing(SCENE_TIMER))
            {
                Hv_App_OsdTimeCounterEnter();
            }
        }
        else
        {
            Hv_App_OsdTimeCounterExit();
        }
    }
    else if (Hv_Mw_OsdSceneIsShowing(SCENE_TIMER))
    {
        Hv_App_OsdTimeCounterExit();
    }
}

VOID Hv_App_Cb_LogoSetting(BOOL bIsShow)
{
    if (bIsShow)
    {
        Hv_Mw_OsdAdjustFunction(E_USERDATA_COLOR_SPACE, ACT_SET_DEFAULT, 0, SET_INTERFACE);
    }
    else
    {
        Hv_Mw_SetFromOsdUserdata(E_USERDATA_COLOR_SPACE);
#if (HV_PROJECT_CONFIG_COLOR_FILTER == HV_CONFIG_ON)
        Hv_Mw_SetFromOsdUserdata(E_USERDATA_COLOR_FILTER);
#endif
    }
}

static const OsdFunctionTable s_astOsdFunctionTable[] =
{
    /* 菜单按键事件 */
    {OSD_EVENT_KEY_PRESS, Hv_App_OsdMenuOperation},
    /* 自动刷新 */
    {OSD_EVENT_TIMER_AUTO_REFRESH, Hv_App_OsdAutoRefresh},
    /* 自动关闭 */
    {OSD_EVENT_TIMER_AUTO_CLOSE, Hv_App_OsdAutoClose},
    /* 长按键 */
    {OSD_EVENT_TIMER_KEY_HOLD, Hv_App_OsdKeyHoldProc},
    /* 信号源状态就绪 */
    {OSD_EVENT_SIGNAL_READY, Hv_App_OsdSignalReady},
    /* 信号源状态改变 */
    {OSD_EVENT_SIGNAL_STATE_CHANGE, Hv_App_OsdSignalStateEnter},
    /* 信号源不支持 */
    {OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT, Hv_App_OsdSignalUnsupportEnter},
    /* 信号源拔出 */
    {OSD_EVENT_SIGNAL_PLUG_OUT, Hv_App_OsdSourcePlugOut},
    /* 进入工厂模式 */
    {OSD_EVENT_FACTORY_ENTER, Hv_App_OsdFactoryEnter},
    /* 退出工厂模式 */
    {OSD_EVENT_FACTORY_EXIT, Hv_App_OsdFactoryExit},
    /* 老化窗口刷新 */
    {OSD_EVENT_FACTORY_AGING_REFRESH, Hv_App_OsdFactoryAgingEnter},
    /* 老化退出 */
    {OSD_EVENT_FACTORY_AGING_EXIT, Hv_App_OsdFactoryAgingExit},
    /* USB OTA升级 */
    {OSD_EVENT_USB_OTA, Hv_App_OsdOtaUpdate},
    /* 隐藏所有OSD */
    {OSD_EVENT_HIDE_ALL, Hv_App_OsdHideAllProc},
};

Status Hv_App_Cb_OsdOperation(OsdEvent *pstEventMsg)
{
    UCHAR8 ucIndex = 0;
    OSD_LOG_DEBUG("EventId = %d", pstEventMsg->usEventId);
    if (pstEventMsg->usEventId == OSD_EVENT_MAX)
    {
        OSD_LOG_DEBUG("Do nothing");
        return HV_FAILURE;
    }

    for (ucIndex = 0; ucIndex < ARRAY_SIZE(s_astOsdFunctionTable); ucIndex++)
    {
        if (pstEventMsg->usEventId == s_astOsdFunctionTable[ucIndex].usEventId)
        {
            if (NULL == s_astOsdFunctionTable[ucIndex].pfOsdFunction)
            {
                return HV_FAILURE;
            }
            s_astOsdFunctionTable[ucIndex].pfOsdFunction(pstEventMsg->usValue);
            break;
        }
    }
    if (ucIndex == ARRAY_SIZE(s_astOsdFunctionTable))
    {
        OSD_LOG_DEBUG("No event operation function, event = %d", pstEventMsg->usEventId);
        return HV_FAILURE;
    }

    Hv_App_OsdCheckAutoShow();

    return HV_SUCCESS;
}
