/**
 * @file        hv_mw_EventHub.c
 * @brief       hv_mw_EventHub c file.
 * @details     This file provides the following functions: \n
 *              (1) handle massages from PM51 \n
 *              (2) send power on reason to system manager \n
 *              (3) send key event to gui task \n
 * @author      HiView SoC Software Team
 * @version     1.0.1
 * @date        2022-09-05
 * @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-08-25   <td>create
 * </table>
*/
    
#include "hv_comm_DataBase.h"
#include "hv_comm_DataType.h"
#include "hv_comm_Event.h"
#include "hv_comm_Assert.h"
#include "hv_comm_Log.h"
#include "hv_vos_Comm.h"
#include "hv_drv_Mailbox.h"
#include "KeyboardConfig.h"
#ifdef CONFIG_USER_IR_ON
#include "IRConfig.h"
#endif
#ifdef CONFIG_USER_GPIO_KEY_ON
#include "hv_drv_GpioKey.h"
#endif
#include "hv_mw_EventHub.h"
#include "hv_mw_OsdDraw.h"
#include "hv_mw_SystemManager.h"
#include "hv_mw_UrgentTask.h"
#include "hv_mw_PowerManager.h"
#include "hv_mw_Channel_Manager.h"
#ifdef CONFIG_USER_TYPE_C_ON
#include "TypecConfig.h"
#endif
#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON))
#include "hv_mw_UsbTask.h"
#endif
#include "hv_chip_Config.h"

#define KEY_STATUS_POLLING_TIME_MS 50

#define KEY_NUM_MAX                6
#define KEY_HOLD_COUNT             (KEY_HOLD_TIME_MS / KEY_STATUS_POLLING_TIME_MS)
#define KEY_DOUBLE_CLICK_COUNT     (KEY_DOUBLE_CLICK_TIME_MS / KEY_STATUS_POLLING_TIME_MS)

static UCHAR8 s_ucKeyValue = 0xff;
static UCHAR8 s_ucCurKeyValue = 0xff;

typedef struct _EventHubTaskHandle
{
    MailboxMsg stRecvMsg;
    MailboxMsg stSendMsg;
    UINT32 uiPowerOnReason;
    UINT32 ucResasonIndex;
    UCHAR8 ucKeyValue;
    UCHAR8 ucKeyHoldingFlag;
    UCHAR8 ucKeyPressFlag;
    UCHAR8 ucKeyPressCount;
    UCHAR8 ucSingleKeyPressCount;
    UCHAR8 ucIRSysCode;
    UCHAR8 ucIRValue;
    UCHAR8 ucIRCount;
}EventHubTaskHandle;

static EventHubTaskHandle g_stEventHubTaskHandle;


Status hv_mw_EventHub_SendOsdEvent(USHORT16 usEventId, USHORT16 usValue)
{
    HV_VOS_QUEUE_S* pOsdQueue = Hv_Mw_System_GetOsdQueue();
    HV_ASSERT_VALID_PTR(pOsdQueue);

    OsdEvent stOsdEvent;
    HV_MEMSET(&stOsdEvent, 0, sizeof(OsdEvent));
    stOsdEvent.usEventId = usEventId;
    stOsdEvent.usValue = usValue;
    HV_LOG_INFO(EVENT, "send: evt[%d] key[%d]\n", usEventId, usValue);
    if (HV_TRUE == Hv_Mw_Power_GetPowerManagerFakeStandyFlag())
    {
        HV_LOG_INFO(EVENT, "fake standby, wakup first.");
        Hw_Mw_Channel_SendNoSignalMsgToPowerManager(HV_TRUE);
        return HV_SUCCESS;
    }
    HV_ASSERT_TRUE(Hv_Vos_QueueSend(pOsdQueue, &stOsdEvent));

    return HV_SUCCESS;
}

static Status LoadPowerOnInitReason(VOID)
{
    HV_ASSERT_SUCCESS(Hv_Drv_MailboxRecvMsg(&g_stEventHubTaskHandle.stRecvMsg));
    if (g_stEventHubTaskHandle.stRecvMsg.stMsgHeader.u8MsgType == E_MAILBOX_CMD_PM_TO_RISC_WAKEUP)
    {
        g_stEventHubTaskHandle.uiPowerOnReason = *(UINT32 *)&g_stEventHubTaskHandle.stRecvMsg.au8MsgBody[0];
        g_stEventHubTaskHandle.ucResasonIndex = g_stEventHubTaskHandle.stRecvMsg.au8MsgBody[4];
        HV_LOG_INFO(EVENT, "Notify power on reason: type[%d] id[%d]", g_stEventHubTaskHandle.uiPowerOnReason, g_stEventHubTaskHandle.ucResasonIndex);
        if (g_stEventHubTaskHandle.uiPowerOnReason == E_WAKE_UP_TYPE_KEY)
        {
#ifdef KEY_WAKE_UP_LOGO_BYPASS
            /* By pass logo & send power on */
            Hv_Mw_OsdSetLogoBypass();
#endif
            hv_mw_EventHub_SendOsdEvent(OSD_EVENT_POWER_ON, (E_WAKE_UP_TYPE_KEY << 8) | GetAdcMappedValue(g_stEventHubTaskHandle.stRecvMsg.au8MsgBody[4]));
        }
    }

    return HV_SUCCESS;
}

static Status SendPowerOnInitReason(VOID)
{
    HV_VOS_QUEUE_S *pSystemQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR(pSystemQueue);

    SystemEvent stSystemEvent;
    HV_MEMSET(&stSystemEvent, 0 ,sizeof(stSystemEvent));
    stSystemEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
    stSystemEvent.usEventId = POWER_EVENT_ID_POWER_ON;
    stSystemEvent.uiValue = g_stEventHubTaskHandle.uiPowerOnReason;

    HV_ASSERT_TRUE(Hv_Vos_QueueSend(pSystemQueue, &stSystemEvent));

    return HV_SUCCESS;
}

USHORT16 Hv_Mw_EventHub_GetPoweronReason(VOID)
{
    return (g_stEventHubTaskHandle.uiPowerOnReason<<8) | g_stEventHubTaskHandle.ucResasonIndex;
}

VOID Hv_Mw_EventHub_TaskStartInit(VOID)
{
    /* load & send power on message to system task */
#ifdef CONFIG_USER_TYPE_C_ON
#if (HV_TYPEC_CONFIG_TYPEC_MODE == TYPEC_MODE_SINK)
    HV_ASSERT_PEEK_SUCCESS_VOID(SendPowerOnInitReason());
#else
    HV_ASSERT_PEEK_SUCCESS_VOID(LoadPowerOnInitReason());
    HV_ASSERT_PEEK_SUCCESS_VOID(SendPowerOnInitReason());
#endif
#else
    HV_ASSERT_PEEK_SUCCESS_VOID(LoadPowerOnInitReason());
    HV_ASSERT_PEEK_SUCCESS_VOID(SendPowerOnInitReason());
#endif
#ifdef CONFIG_USER_GPIO_KEY_ON
    Hv_Drv_InitGpioKey();
#endif
    return;
}


UCHAR8 Hv_Mw_EventHub_GetCurKeyValue(void)
{
    return s_ucCurKeyValue;
}

VOID Hv_Mw_EventHubTaskHandle(VOID *arg)
{
    Event stEventMsg;
    Status uiRet = HV_FAILURE;
    UCHAR8 ucRetry = 100;
    UCHAR8 ucIrKeyValue = 0xff;
    UINT32 uiSysCode = 0;
    HV_MEMSET(&stEventMsg, 0 ,sizeof(Event));
    MailboxMsg stMailboxMsg = { 0 };
    HV_VOS_QUEUE_S *pEventHubQueue = Hv_Mw_System_GetEventHubQueue();
    HV_ASSERT_VALID_PTR_VOID(pEventHubQueue);
#ifdef CONFIG_USER_TYPE_C_ON
#if (HV_TYPEC_CONFIG_TYPEC_MODE == TYPEC_MODE_SINK)
    HV_ASSERT_PEEK_SUCCESS_VOID(LoadPowerOnInitReason());
#else
    Hv_Mw_EventHub_TaskStartInit();
#endif
#else
    Hv_Mw_EventHub_TaskStartInit();
#endif

    for (;;)
    {
        uiRet = HV_FAILURE;
        #ifdef SW_DUMMY_DEBUG
        HV_WT32(SW_DUMMY_EVENT_TASK, (HV_RD32(SW_DUMMY_EVENT_TASK)+1));
        #endif
        if (Hv_Vos_QueueTimedRecv(pEventHubQueue, (VOID *)&stEventMsg, KEY_STATUS_POLLING_TIME_MS))
        {
            stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_NULL;
            /**< standby msg received */
            switch (stEventMsg.usEventId)
            {
                case EVENT_HUB_REV_MSG_ID_ENTER_STANDBY:
                {
                    HV_LOG_INFO(EVENT_HUB, "System go to Standby,Bye!!");
                    Hv_Vos_TaskEnterCritical();
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_STAND_BY;
                    #ifdef HV_PROJECT_CONFIG_AUTO_POWEROFF_MINUTES
                    /* open auto poweroff or not. */
                    if (HV_COMMON_DATABASE_GET(UserData, ucAutoPowerOff))
                    {
                        stMailboxMsg.au8MsgBody[0] = 0xaa;
                    }
                    else
                    {
                        stMailboxMsg.au8MsgBody[0] = 0x0;
                    }
                    #endif
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_ENTER_POWEROFF:
                {
                    HV_LOG_INFO(EVENT_HUB, "System go to Poweroff,Bye!!");
                    Hv_Vos_TaskEnterCritical();
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_POWER_OFF_ACK;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_BOOTUP_TOPM:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_NORMAL;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_OFF:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_OFF;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_ON:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_BREATH:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_BREATH;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_ON1:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON1;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_ON2:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON2;
                    break;
                }
                case EVENT_HUB_REV_MSG_ID_PMLED_ON3:
                {
                    stMailboxMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON3;
                    break;
                }
                default:
                {
                    break;
                }
            }

            while ((HV_SUCCESS != uiRet) && (ucRetry--))
            {
                uiRet = Hv_Drv_MailboxSendMsg(&stMailboxMsg);
                Hv_Vos_Delayus(1000);
            }

        }
        else
        {
            /* read mailbox from PM51 */
            if (Hv_Drv_MailboxRecvMsg(&g_stEventHubTaskHandle.stRecvMsg) == HV_SUCCESS)
            {
                switch (g_stEventHubTaskHandle.stRecvMsg.stMsgHeader.u8MsgType)
                {
                    case E_MAILBOX_CMD_PM_TO_RISC_KEY_VAL:
                    {
                        Hv_Drv_MailboxGetKeyValue(&g_stEventHubTaskHandle.stRecvMsg, &g_stEventHubTaskHandle.ucKeyValue);
                        s_ucCurKeyValue = g_stEventHubTaskHandle.ucKeyValue;
                        if ((g_stEventHubTaskHandle.ucKeyValue == s_ucKeyValue)
                            && (g_stEventHubTaskHandle.ucSingleKeyPressCount < KEY_DOUBLE_CLICK_COUNT))
                        {
                            hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_DOUBLE_CLICK, GetAdcMappedValue(s_ucKeyValue));
                            s_ucKeyValue = 0xff;
                        }
                        else
                        {
                            s_ucKeyValue = g_stEventHubTaskHandle.ucKeyValue;
                            /*if (GetAdcMappedValue(s_ucKeyValue)==OSDEVT_KEY_POWER)
                            {
                                //Hv_Mw_Power_SendPoweroffToPowerManager();
                            }*/
                            #ifdef MAP_LONG_MENU_TO_POWER
                            if (GetAdcMappedValue(s_ucKeyValue)!=OSDEVT_KEY_ENTER)
                            #endif
                            #ifdef SINGLE_RELEASE_COMBO_PRESS
                            if (s_ucKeyValue >= E_COMBO_KEY_VAL_0)
                            #endif
                            {
                                hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_PRESS, GetAdcMappedValue(s_ucKeyValue));
                            }
                        }
                        g_stEventHubTaskHandle.ucSingleKeyPressCount = 0;
                        g_stEventHubTaskHandle.ucKeyPressFlag = HV_TRUE;
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_KEY_UPSPRING:
                    {
                        Hv_Drv_MailboxGetKeyValue(&g_stEventHubTaskHandle.stRecvMsg, &g_stEventHubTaskHandle.ucKeyValue);
                        /*if (GetAdcMappedValue(s_ucKeyValue)==OSDEVT_KEY_POWER)
                        {
                            Hv_Mw_Power_SendPoweroffToPowerManager();
                        }*/
                        #ifdef MAP_LONG_MENU_TO_POWER
                        if (GetAdcMappedValue(s_ucKeyValue)==OSDEVT_KEY_ENTER)
                        {
                            hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_PRESS, GetAdcMappedValue(s_ucKeyValue));
                        }
                        #endif
                        #ifdef SINGLE_RELEASE_COMBO_PRESS
                        if ((s_ucKeyValue<E_COMBO_KEY_VAL_0) && (g_stEventHubTaskHandle.ucKeyHoldingFlag != HV_TRUE))
                        {
                           hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_PRESS, GetAdcMappedValue(s_ucKeyValue));
                        }
                        #endif
                        s_ucCurKeyValue = 0xff;
                        if ((g_stEventHubTaskHandle.ucKeyHoldingFlag == HV_TRUE) && (g_stEventHubTaskHandle.ucKeyPressFlag == HV_TRUE))
                        {
                            hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_RELEASE, GetAdcMappedValue(g_stEventHubTaskHandle.ucKeyValue));
                            g_stEventHubTaskHandle.ucKeyHoldingFlag = HV_FALSE;
                        }
                        g_stEventHubTaskHandle.ucKeyPressFlag = HV_FALSE;
                        g_stEventHubTaskHandle.ucKeyPressCount = 0;
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_POWER_OFF:
                    {
                        Hv_Mw_Power_SendPoweroffToPowerManager();
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_FACTORY_MODE:
                    {
                        HV_LOGI("factory mode.");
#ifdef FACTORY_MODE_LOGO_BYPASS
                        /* By pass logo & send enter factory mode */
                        Hv_Mw_OsdSetLogoBypass();
#endif
                        HV_COMMON_DATABASE_SET(SystemData, bFactoryMode, HV_TRUE);

                        hv_mw_EventHub_SendOsdEvent(OSD_EVENT_FACTORY_ENTER, GetAdcMappedValue(g_stEventHubTaskHandle.ucKeyValue));
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_LOCK_MODE:
                    {
                        HV_LOGI("lock mode.");
#ifdef CONFIG_FACTORY_MODE_WITH_DC
#ifdef FACTORY_MODE_LOGO_BYPASS
                        /* By pass logo & send enter factory mode */
                        Hv_Mw_OsdSetLogoBypass();
#endif
                        HV_COMMON_DATABASE_SET(SystemData, bFactoryMode, HV_TRUE);
                        hv_mw_EventHub_SendOsdEvent(OSD_EVENT_FACTORY_ENTER, GetAdcMappedValue(g_stEventHubTaskHandle.ucKeyValue));
#endif
                        break;
                    }
                    #ifdef CONFIG_USER_IR_ON
                    case E_MAILBOX_CMD_PM_TO_RISC_IR_VAL:
                    {
                        Hv_Drv_MailboxGetIRKeyValue(&g_stEventHubTaskHandle.stRecvMsg, &g_stEventHubTaskHandle.ucIRSysCode, &g_stEventHubTaskHandle.ucIRValue);
                        HV_LOGI("ucSysCode %x, uiAdcValue %x", g_stEventHubTaskHandle.ucIRSysCode, g_stEventHubTaskHandle.ucIRValue);
                        ucIrKeyValue = GetIRMappedValue(g_stEventHubTaskHandle.ucIRSysCode, g_stEventHubTaskHandle.ucIRValue);
                        if (0xff != ucIrKeyValue)
                        {
                            hv_mw_EventHub_SendOsdEvent(OSD_EVENT_IR_KEY, ucIrKeyValue);
                        }
                        g_stEventHubTaskHandle.ucIRCount = 0;
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_IR_REPEAT:
                    {
                        g_stEventHubTaskHandle.ucIRCount++;

                        if (g_stEventHubTaskHandle.ucIRCount>HV_CONFIG_IR_REPEAT_NUM)
                        {
                            Hv_Drv_MailboxGetIRKeyValue(&g_stEventHubTaskHandle.stRecvMsg, &g_stEventHubTaskHandle.ucIRSysCode, &g_stEventHubTaskHandle.ucIRValue);
                            ucIrKeyValue = GetIRMappedValue(g_stEventHubTaskHandle.ucIRSysCode, g_stEventHubTaskHandle.ucIRValue);
                            if (0xff != ucIrKeyValue)
                            {
                                hv_mw_EventHub_SendOsdEvent(OSD_EVENT_IR_REPEAT_KEY, ucIrKeyValue);
                            }
                        }
                        break;
                    }
                    #endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DP_NOSTAND_CABLE_ENABLE)
                    case E_MAILBOX_CMD_PM_TO_RISC_DP0_AUXN_INT:
                    {
                        HV_VOS_QUEUE_S* pSysQueue = Hv_Mw_System_GetSystemQueue();
                        HV_ASSERT_VALID_PTR_VOID(pSysQueue);
                        SystemEvent stSystemEvent = {0};
                        stSystemEvent.enEventType = SYSTEM_REV_EVENT_TYPE_INPUTPORT;
                        stSystemEvent.ucPortIndex = LINK_PORT_INDEX_DP_RX0;
                        stSystemEvent.usEventId = InputPortEventId_DP_CableInt;
                        Hv_Vos_QueueSend(pSysQueue, &stSystemEvent);
                        break;
                    }
                    case E_MAILBOX_CMD_PM_TO_RISC_DP1_AUXN_INT:
                    {
                        HV_VOS_QUEUE_S* pSysQueue = Hv_Mw_System_GetSystemQueue();
                        HV_ASSERT_VALID_PTR_VOID(pSysQueue);
                        SystemEvent stSystemEvent = {0};
                        stSystemEvent.enEventType = SYSTEM_REV_EVENT_TYPE_INPUTPORT;
                        stSystemEvent.ucPortIndex = LINK_PORT_INDEX_DP_RX1;
                        stSystemEvent.usEventId = InputPortEventId_DP_CableInt;
                        Hv_Vos_QueueSend(pSysQueue, &stSystemEvent);
                        break;
                    }
#endif
                    case E_MAILBOX_CMD_PM_TO_RISC_WAKEUP: /**< pass through */
                    default:
                        /* do nothing */
                        break;
                }
            }
            else if ((g_stEventHubTaskHandle.ucKeyPressFlag == HV_TRUE) && (g_stEventHubTaskHandle.ucKeyHoldingFlag == HV_FALSE))
            {
                #ifdef MAP_LONG_MENU_TO_POWER
                if (GetAdcMappedValue(g_stEventHubTaskHandle.ucKeyValue)==OSDEVT_KEY_ENTER)
                {
                    if (++g_stEventHubTaskHandle.ucKeyPressCount >= KEY_HOLD_COUNT*5)
                    {
                        Hv_Mw_Power_SendPoweroffToPowerManager();
                        g_stEventHubTaskHandle.ucKeyValue = OSDEVT_KEY_NONE;
                    }
                }
                else
                #endif
                if (++g_stEventHubTaskHandle.ucKeyPressCount >= KEY_HOLD_COUNT)
                {
                    hv_mw_EventHub_SendOsdEvent(OSD_EVENT_KEY_HOLD, GetAdcMappedValue(g_stEventHubTaskHandle.ucKeyValue));
                    g_stEventHubTaskHandle.ucKeyHoldingFlag = HV_TRUE;
                    g_stEventHubTaskHandle.ucKeyPressCount = 0;
                }
            }
            else
            {
                g_stEventHubTaskHandle.ucSingleKeyPressCount++;
                if (g_stEventHubTaskHandle.ucSingleKeyPressCount > 0xfe)
                {
                    g_stEventHubTaskHandle.ucSingleKeyPressCount = 0xfe;
                }
                /* do nothing */
            }
        }
        /* switch task */
        Hv_Vos_TaskYield();
    }
}

