/**
 * @file hv_mw_OsdUserdata.c
 * @brief osd userdata c file.
 * @details This file provides the following functions: \n
 *          (1) Osd userdata 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>shanpeng     <td>2022-09-01      <td>create
 * </table>
 */
#ifdef OSD_ITEM_BIND_USERDATA_BY_TOOL

#include "hv_mw_OsdLog.h"
#include "hv_mw_OsdUserdata.h"
#include "hv_app_Function.h"
#include "hv_drv_Gpio.h"

VOID Hv_Mw_SetFromOsdUserdata(UserdataId enUserdata)
{
    HV_ASSERT_TRUE_VOID((E_USERDATA_NONE != enUserdata) && (enUserdata < E_USERDATA_MAX));
    SHORT16 sValue = Hv_App_GetOsdDataValue(enUserdata);
    Hv_Mw_OsdAdjustFunction(enUserdata, ACT_SET, sValue, SET_INTERFACE);
}

VOID Hv_Mw_OsdUserdataUpdate(UserdataId enWhichData)
{
    UserdataProp stOsdDataProp = { 0 };
    Hv_App_OsdGetUserdata(enWhichData, &stOsdDataProp);
    SHORT16 sOsdValue = 0;

    OSD_LOG_DEBUG("Update userdata: %s", Hv_App_GetUserdataName(enWhichData));

    if (E_NO_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = stOsdDataProp.sRealValue;
        OSD_LOG_DEBUG("Get no mapped value = %d", sOsdValue);
    }
    else if (E_ENUM_MAP == stOsdDataProp.enMappingType)
    {
        UCHAR8 ucValueId = 0;
        for (; ucValueId < stOsdDataProp.stEnumMap.usCount; ucValueId++)
        {
            if (stOsdDataProp.sRealValue == stOsdDataProp.stEnumMap.asRealValueMapTable[ucValueId])
            {
                break;
            }
        }
        sOsdValue = ucValueId;
        if (sOsdValue >= stOsdDataProp.stEnumMap.usCount)
        {
            OSD_LOG_ERROR("Userdata-%d, real value = %d not found!", enWhichData, stOsdDataProp.sRealValue);
            sOsdValue = 0;
        }
        else
        {
            OSD_LOG_DEBUG("Get enum map value = %d (real value=%d)", sOsdValue, stOsdDataProp.sRealValue);
        }
    }
    else if (E_LINEAR_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = LINEAR_MAPPING_VALUE(stOsdDataProp.sRealValue, stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue,
                             stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue);
        OSD_LOG_DEBUG("Get linear map value = %d (real value=%d)", sOsdValue, stOsdDataProp.sRealValue);
    }
    else if (E_LINEAR_REVERT_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = LINEAR_REVERT_MAPPING_VALUE(stOsdDataProp.sRealValue, stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue,
                             stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue);
        OSD_LOG_DEBUG("Get linear revert map value = %d (real value=%d)", sOsdValue, stOsdDataProp.sRealValue);
    }
    else
    {
        OSD_LOG_ERROR("Userdata-%d mapping type error!", enWhichData);
        return;
    }

    if (sOsdValue != stOsdDataProp.sOsdValue)
    {
        OSD_LOG_DEBUG("Update OsdUserdata-%d value: %d to %d", enWhichData, stOsdDataProp.sOsdValue, sOsdValue);
        Hv_App_OsdSetUserdata(enWhichData, sOsdValue);
    }
}

VOID Hv_Mw_OsdUserdataUpdateAll(VOID)
{
    OSD_LOG_DEBUG("Osd userdata sync, num = %d", E_USERDATA_MAX);
    for (USHORT16 usId = 1; usId < E_USERDATA_MAX; usId++)
    {
        Hv_Mw_OsdUserdataUpdate(usId);
    }
}

SHORT16 Hv_Mw_OsdGetMappedOsdValue(UserdataId enWhichData, SHORT16 sRealValue)
{
    UserdataProp stOsdDataProp = { 0 };
    Hv_App_OsdGetUserdata(enWhichData, &stOsdDataProp);
    SHORT16 sOsdValue = 0;

    OSD_LOG_DEBUG("Update userdata: %s", Hv_App_GetUserdataName(enWhichData));

    if (E_NO_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = sRealValue;
        OSD_LOG_DEBUG("Get no mapped value = %d", sOsdValue);
    }
    else if (E_ENUM_MAP == stOsdDataProp.enMappingType)
    {
        UCHAR8 ucValueId = 0;
        for (; ucValueId < stOsdDataProp.stEnumMap.usCount; ucValueId++)
        {
            if (sRealValue == stOsdDataProp.stEnumMap.asRealValueMapTable[ucValueId])
            {
                break;
            }
        }
        sOsdValue = ucValueId;
        if (sOsdValue >= stOsdDataProp.stEnumMap.usCount)
        {
            OSD_LOG_ERROR("Userdata-%d, real value = %d not found!", enWhichData, sRealValue);
            sOsdValue = 0;
        }
        else
        {
            OSD_LOG_DEBUG("Get enum map value = %d (real value=%d)", sOsdValue, sRealValue);
        }
    }
    else if (E_LINEAR_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = LINEAR_MAPPING_VALUE(sRealValue, stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue,
                             stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue);
        OSD_LOG_DEBUG("Get linear map value = %d (real value=%d)", sOsdValue, sRealValue);
    }
    else if (E_LINEAR_REVERT_MAP == stOsdDataProp.enMappingType)
    {
        sOsdValue = LINEAR_REVERT_MAPPING_VALUE(sRealValue, stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue,
                             stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue);
        OSD_LOG_DEBUG("Get linear revert map value = %d (real value=%d)", sOsdValue, sRealValue);
    }
    else
    {
        HV_ASSERT_TRUE_RET(stOsdDataProp.enMappingType <= E_LINEAR_REVERT_MAP, 0);
    }

    return sOsdValue;
}

SHORT16 Hv_Mw_OsdGetMappedRealValue(UserdataId enWhichData, SHORT16 sOsdValue)
{
    UserdataProp stOsdDataProp = { 0 };
    Hv_App_OsdGetUserdata(enWhichData, &stOsdDataProp);
    SHORT16 sCurRealValue = 0;

    OSD_LOG_DEBUG("Get %s's real value:", Hv_App_GetUserdataName(enWhichData));

    if (E_NO_MAP == stOsdDataProp.enMappingType)
    {
        sCurRealValue = sOsdValue;
        OSD_LOG_DEBUG("OsdUserdata-%d OsdValue: %d no map to real = %d", enWhichData, sOsdValue, sCurRealValue);
    }
    else if (E_ENUM_MAP == stOsdDataProp.enMappingType)
    {
        HV_ASSERT_TRUE_RET(sOsdValue < stOsdDataProp.stEnumMap.usCount, 0);
        sCurRealValue = stOsdDataProp.stEnumMap.asRealValueMapTable[sOsdValue];
        OSD_LOG_DEBUG("OsdUserdata-%d OsdValue: %d enum map to real = %d", enWhichData, sOsdValue, sCurRealValue);
    }
    else if (E_LINEAR_MAP == stOsdDataProp.enMappingType)
    {
        sCurRealValue = LINEAR_MAPPING_VALUE(sOsdValue, stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue,
                                             stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue);
        OSD_LOG_DEBUG("OsdUserdata-%d OsdValue: %d linear map to real = %d", enWhichData, sOsdValue, sCurRealValue);
    }
    else if (E_LINEAR_REVERT_MAP == stOsdDataProp.enMappingType)
    {
        sCurRealValue = LINEAR_REVERT_MAPPING_VALUE(sOsdValue, stOsdDataProp.sMinValue, stOsdDataProp.sMaxValue,
                                             stOsdDataProp.stLinerMap.sRealMinValue, stOsdDataProp.stLinerMap.sRealMaxValue);
        OSD_LOG_DEBUG("OsdUserdata-%d OsdValue: %d linear revert map to real = %d", enWhichData, sOsdValue, sCurRealValue);
    }
    else
    {
        HV_ASSERT_TRUE_RET(stOsdDataProp.enMappingType <= E_LINEAR_REVERT_MAP, 0);
    }

    return sCurRealValue;
}

SHORT16 Hv_Mw_OsdAdjustFunction(UserdataId enWhichData, AdjustAct enAdjustAct, SHORT16 sAdjustValue, UCHAR8 ucFlag)
{
    HV_ASSERT_TRUE_RET((E_USERDATA_NONE != enWhichData) && (enWhichData < E_USERDATA_MAX), 0);
    UserdataProp stProp = { 0 };
    SHORT16 sValue = 0;

    Hv_App_GetOsdUserdataProp(enWhichData, &stProp);

    switch (enAdjustAct)
    {
        case ACT_SET:
        {
            sValue = sAdjustValue;
            if (sValue > stProp.sMaxValue)
            {
                OSD_LOG_WARN("Userdata-%d: set value = %d, limit to max = %d", enWhichData, sValue, stProp.sMaxValue);
                sValue = stProp.sMaxValue;
            }
            else if (sValue < stProp.sMinValue)
            {
                OSD_LOG_WARN("Userdata-%d: set value = %d, limit to min = %d", enWhichData, sValue, stProp.sMinValue);
                sValue = stProp.sMinValue;
            }
            
            if (enWhichData == E_USERDATA_VIDEOSOURCE)
            {
                switch (sAdjustValue)
                {
                    case UD_VIDEOSOURCE_V_HDMI1:
                    {
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YA, GPIO_LEVEL_HIGH);
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YB, GPIO_LEVEL_LOW);
                        break;
                    }
                    case UD_VIDEOSOURCE_V_HDMI2:
                    {
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YA, GPIO_LEVEL_LOW);
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YB, GPIO_LEVEL_LOW);
                        break;
                    }
                    case UD_VIDEOSOURCE_V_USB_C:
                    {
                        break;
                    }
                    case UD_VIDEOSOURCE_V_DP:
                    {
                        break;
                    }
                    default:
                    {
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YA, GPIO_LEVEL_HIGH);
                        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_CH444G_YB, GPIO_LEVEL_LOW);
                        break;
                    }
                }
            }
            break;
        }

        case ACT_SET_DEFAULT:
        {
            sValue = GET_OSD_MAP_VALUE(enWhichData, stProp.sRealDefaultValue);
            break;
        }

        case ACT_INCREASE:
        {
            sValue = stProp.sOsdValue;
            sValue += sAdjustValue;
            if (sValue > stProp.sMaxValue)
            {
                if (stProp.bCircle)
                {
                    sValue = stProp.sMinValue;
                }
                else
                {
                    sValue = stProp.sMaxValue;
                }
            }
            break;
        }

        case ACT_DECREASE:
        {
            sValue = stProp.sOsdValue;
            sValue -= sAdjustValue;
            if (sValue < stProp.sMinValue)
            {
                if (stProp.bCircle)
                {
                    sValue = stProp.sMaxValue;
                }
                else
                {
                    sValue = stProp.sMinValue;
                }
            }
            break;
        }

        default:
        {
            return sValue;
        }
    }

    /* If just set interface, do not check userdata if equal */
    if ((0 == (ucFlag & SET_OSDDATA)) || (ucFlag & SET_FORCE))
    {
        OSD_LOG_DEBUG("Set %s = %d -> %d", Hv_App_GetUserdataName(enWhichData), stProp.sOsdValue, sValue);
        Hv_App_SetFuncInterface(enWhichData, sValue, ucFlag);
    }
    else if (stProp.sOsdValue != sValue)
    {
        OSD_LOG_DEBUG("Update %s = %d -> %d", Hv_App_GetUserdataName(enWhichData), stProp.sOsdValue, sValue);
        Hv_App_SetFuncInterface(enWhichData, sValue, ucFlag);
    }
    else
    {
        OSD_LOG_DEBUG("No need update %s = %d", Hv_App_GetUserdataName(enWhichData), stProp.sOsdValue);
    }

    return sValue;
}

#endif