/**
 * @file hv_mw_Channel_Manager.h
 * @brief Header file of ChannelManager module.
 * 
 * @verbatim
 * ==============================================================================
 *                        ##### How to use #####
 * ==============================================================================
 * (+) At first.
 * (+) Use Hv_Mw_Channel_ManagerInit(...) to initial ChannelManager.
 * (+) Use Hv_Mw_Channel_SendInnerMsg(...) send a message to ChannelManager Inner MessageQueue immediately.
 * (+) Use Hv_Mw_Channel_ProcSystemQueueMsg(...) will process one Message from SystemQueue. 
 * (+) Use Hv_Mw_Channel_ProcInnerMsgs(...) will proc all Channel inner MessageQueue messages once time. 
 * (+) Use Hv_Mw_Channel_HasInnerMsgs(...) judge whether there are messages in the Channel messsage pool.
 * 
 * @endverbatim
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-10
 */
#ifndef __SDK_MIDDLEWARE_RUNTIME_SYSTEMMANAGER_CHANNEL_MANAGER_INC_CHANNEL_MANAGER_H__
#define __SDK_MIDDLEWARE_RUNTIME_SYSTEMMANAGER_CHANNEL_MANAGER_INC_CHANNEL_MANAGER_H__


#include "hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_comm_Event.h"
#include "hv_comm_Timer.h"
#include "hv_mw_StateMachine.h"

/*注意此处宏定义必须加()，否则会有运算符优先级bug,a % MAX_CHANNEL_QUEUE_SIZE运算的结果是
(a % HV_BOARD_CONFIG_MAX_CHANNEL_NUM) * 20!!!! */
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#define MAX_CHANNEL_QUEUE_SIZE                              (2 * 20)
#else
#define MAX_CHANNEL_QUEUE_SIZE                              (1 * 20)
#endif

typedef struct _ChannelInnerMsgQueue
{
    USHORT16 usWriteAddr;           /* 写地址 */
    USHORT16 usReadAddr;            /* 读地址 */
    ChannelEvent astFifo[MAX_CHANNEL_QUEUE_SIZE];
}__attribute__((aligned(4)))ChannelInnerMsgQueue;

typedef struct _SearchStrategy
{
    UCHAR8          ucGuiPortIndex;         /*搜索的端口号对应的是OSD菜单定义的编号 0, 1, 2, 3 ...*/
    UCHAR8          ucSearched;             /*记录是否被搜索过*/
    USHORT16        usSearchTimes;          /*端口已搜索次数*/
}SearchStrategy;

typedef struct _ChannelFlashConfig
{
    BOOL                bFlashSubFakeVideoSw;      /*flash中保存的放大镜开关*/
    PxpMode             enFlashPxPMode;            /*flash中保存的PXP模式开关*/
}ChannelFlashConfig;

typedef struct _ChannelData
{
    ChannelState            enCurrentCHState;               /*当前通道资源配置的即时状态*/
    ChannelType             enChannelType;                  /*通道类型，0-Main channel，1-Sub channel，PIB/PBP开启时才需要配置辅通道*/
    LinkPortIndex           enChannelSrcLinkPortIndex;      /*当前通道绑定的具体HDMI/DP链路编号*/
    LinkPortIndex           enLastChannelSrcLinkPortIndex;  /*最后通道绑定的具体HDMI/DP链路编号*/    
    HV_TIMER_S*             pstPeriodSearchTimer;           /*进入search态启动的搜索port定时器*/
    HV_TIMER_S*             pstAVcheckStableTimer;          /*config态进入active态前启动的检查audio video mute模块工作正常的定时器*/
    HV_TIMER_S*             pstNoSignalTimer;               /*无信号态启动的定时器*/
    HV_TIMER_S*             pstVideoMuteTimer;              /*video mute模块正常后, 启动的防抖定时器。在timing change场景下mute很快正常，
                                                    此时不能解mute需要等待DPU配置完成才能解mute，非timingchange case直接解mute*/
    HV_TIMER_S*             pstAudioMuteTimer;              /*audio mute模块正常后, 启动的防抖定时器。在timing change场景下mute很快正常，
                                                    此时不能解mute需要等待DPU配置完成才能解mute，非timingchange case直接解mute*/

    HV_TIMER_S*             pstBurnInPeriodCheckTimer;      /*老化模式下的周期性timer 用于检查端口状态及切换老化pattern*/
    HV_TIMER_S*             pstAvWatchdogTimer;             /*video正常显示时，轮询检查系统状态*/
    HV_TIMER_S*             pstAudioFsCheckTimer;           /*FS change时，等待多久去查audio状态*/

    BOOL                    bAVStable;                      /*audio video mute模块是否正常工作标志位*/
    BOOL                    bOutofRangeFlag;                /*framesync模式下DTC动态计算的时钟频率是否超过屏规格*/
    BOOL                    bNoSignalLongTimes;             /*true 该通道处于长时间无信号状态，如果2个通道均置位，则进入待机或者老化*/
    BOOL                    bStandByFlag;                   /*是否发送了standBy消息，0 未发送，1已发送*/
    UCHAR8                  ucBurnInPattern;                /*用于记录当前使用的pattern*/
    USHORT16                usAVStableCheckTimes;           /*timer检查次数记录，5次以后强制进入active态*/
    USHORT16                usNoSignalCheckTimes;           /*NoSignal定时器time out次数,用于记录进入无信号状态的时间*/
    USHORT16                usTotalSearchTimes;             /*用于记录search态已搜索的次数,超过配置的最大次数进入无信号状态*/
    UINT32                  uiErrorCode;                    /*用于记录当前Channel的配置的错误，可以用于显示获取timing错误，配置错误等等*/
    UINT32                  uiMuteStatus;                   /*记录当前通道mute状态*/
    UINT32                  uiEnterNoSignalCount;           /*记录当前通道无信号时进入NoSignal的次数*/
    VideoTimingParam        stRxVideoTiming;              /*从RX获取到的原始timing, VideoConfigParams存储的是可能被修正的 timing*/
    AudioTimingParam        stRxAudioTiming;               /*从RX获取到的audio相关参数*/
    VideoConfigParams       stVideoConfigParams;          /*Dpu config链路需要使用的所有参数*/    
    ChanelSignalState       enChanelSignalState;          /*通道选择的某一端口信号状态，主要用于给OSD显示使用*/

    Status (*pfMuteInit)(VOID);
    Status (*pfSetMuteTiming)(const VideoTimingParam*  pstVideoTiming, UINT32 uiPixelClock, BOOL bOsdVrrEnable);
    UINT32 (*pfGetMuteState)(VOID);
    UINT32 (*pfGetMuteStatus)(VOID);
    Status (*pfMuteForceFreeRun)(BOOL bSwitch);
    VOID (*pfMuteClearEn)(VOID);
    Status (*pfDpuScalerConfig)(const VideoConfigParams* pstVideoConfigParams);
    UCHAR8 (*pfPQCallback)(PQCALLBACKMODE enMode, const VOID *pvVideoConfigParams);
}ChannelData;

typedef struct _ChannelManager
{
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    ChannelData             astChannelData[2];          /*存储通道数据*/
#else
    ChannelData             astChannelData[1];          /*存储通道数据*/
#endif
    ChannelInnerMsgQueue    stChInnerMsgQueue;          /*内部消息队列用于缓存挂在SystemTask其他模块发给Channel模块的消息*/
    BOOL                    bOSDActive;                 /*当前用户是否操作OSD菜单*/
    ChannelFlashConfig      stChannelFlashConfig;       /*flash中保存的变量，给channel使用，与OSD做隔离*/
    BOOL                    bSignalInterruption;        /* 睡眠过程中是否有信号打断 */
}__attribute__((aligned(4)))ChannelManager;

typedef struct _ChannelStateMachine
{
    USHORT16        usAcceptStates;
    ChanelEventId   enEventId;
    Status          (*pfActionHandle)(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
    ChannelState    enNextSuccessState;
    ChannelState    enNextFailState;
}ChannelStateMachine;

/**
 * @brief proc all of the messages in the channel inner Message pool once time.
 * @param[in] pstChannelManager pointer to ChannelManager.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_ProcInnerMsgs(VOID);

/**
 * @brief proc one SystemEvent messsage form System messageQueue.
 * @param[in] pstSystemEvent pointer to message to process.
 * @param[in] pstChannelManager pointer to ChannelManager.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_ProcSystemQueueMsg(const SystemEvent* pstSystemEvent);

/**
 * @brief judge whether there are messages in the channel messsage pool.
 * @param[in] None.
 * @return BOOL type of result, 0-empty, 1-not empty.
 */
BOOL Hv_Mw_Channel_HasInnerMsgs( VOID );

/**
 * @brief send a message to the channel messsage pool.
 * @param[in] point to ChannelEvent*  messages type to send.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_SendInnerMsg(const ChannelEvent* pstChannelEvent);

/**
 * @brief get ChannelManager object.
 * @param[in] None.
 * @return pointer to ChannelManager object.
 */
const ChannelManager* Hv_Mw_Channel_GetManager();

/**
 * @brief get ChannelManager flash data.
 * @return value.
 */
ChannelFlashConfig* Hv_Mw_Channel_GetManagerData(VOID);

/**
 * @brief initial ChannelManager object.
 * @param[in] pointer of ChannelManager object to be initial.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_Manager_Init(VOID);

/**
 * @brief Get channel bind port and state.
 * @param[in] ChannelType: main or sub.
 * @param[out] LinkPortIndex:bind port idnex. ChanelSignalState:signal state.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_GetSignalState(ChannelType enChannelType, LinkPortIndex* penChannelSrcLinkPortIndex, ChanelSignalState* penChanelSignalState);

/**
 * @brief Get channel bind port realtime video timing,ps:in vrr case framerate will change.
 * @param[in] ChannelType: main or sub.
 * @param[out] VdeTimingParam:RX video timing.
 * @return Status, 0-SUCCESS, 1-HV_FAILURE.
 */
Status Hv_Mw_Channel_GetVideoTiming(ChannelType enChannelType, VideoTimingParam* pstVideoTiming);

LinkPortIndex Hv_Mw_Channel_ConvertGuiToMwPortIndex(UCHAR8 ucGuiPortIndex);

/**
 * @brief 设置音源接口.
 * @param[in] uiValue:0-主通道/左 1:辅通道/右
 * @param[out] NULL
 * @return 0-success other-failure
 */
Status Hv_Mw_Channel_AudioSourceConfig(ChannelType enChannelType);

/**
 * @brief 判断音源输入是否在当前通道接口.
 * @param[in] enChannelType:CHANNEL_TYPE_MAIN-主通道/左 CHANNEL_TYPE_SUB:辅通道/右
 * @param[out] NULL
 * @return HV_TRUE-音源配置在当前通道, False-音源配置未在当前通道
 */
BOOL Hv_Mw_Channel_IsAudioOnThisChannel(ChannelType enChannelType);
/**
 * @brief 设置当前OSD菜单状态.
 * @param[in] uiValue:0-invalid 1:valid
 * @param[out] NULL
 * @return NULL
 */
VOID Hv_Mw_Channel_SetOSDActive(BOOL bStatus);
/**
 * @brief 查询当前OSD菜单状态.
 * @param[in] NULL
 * @param[out] NULL
 * @return 0-invalid 1:valid
 */
BOOL Hv_Mw_Channel_GetOSDActive(VOID);
/**
 * @brief 系统mute函数，包括声音和图像.
 * @param[in] ChannelType：主副通道
 * @param[out] NULL
 * @return NULL
 */
VOID Hv_Mw_Channel_MuteOn(ChannelType enChannelType);
/**
 * @brief 系统unmute函数，包括声音和图像.
 * @param[in] ChannelType：主副通道
 * @param[out] NULL
 * @return NULL
 */
Status Hv_Mw_Channel_MuteOff(ChannelType enChannelType);
/**
 * @brief 查询当前是否有信号在显示.
 * @param[in] NULL
 * @param[out] NULL
 * @return 0-invalid 1:valid
 */
UCHAR8 Hv_Mw_Channel_GetChannelOnDisplay(VOID);

PxpMode Hv_Mw_Channel_GetPxpMode();

VOID Hv_Mw_Channel_UpdateVideoConfigParam(ChannelType enChannelType, VideoConfigParams stVideoConfigParams);

VOID Hv_Mw_Channel_UpdateMainRxFakeVideoParam(MainRxFakeVideoParam stMainRxFakeVideoParam);

Status Hw_Mw_Channel_SendPowerOffToPowerManager(VOID);

/**
 * @brief 发送无信号进待机命令给power manger.
 * @param[in] bEnterFlag 1：进待机，2：从待机进入normal.
 */
Status Hw_Mw_Channel_SendNoSignalMsgToPowerManager(BOOL bEnterFlag);

/**
 * @brief 停止AvWatchdogTimer
 * @param[in] NULL
 * @param[out] NULL.
 * @return NULL
 */
VOID Hv_Mw_Channel_StopAvWatchdogTimer(VOID);
LinkPortIndex Hv_Mw_Channel_GetAudioSelInputPortIndex(VOID);

/**
 * @brief 判断Main是否有信号识别
 */
Status Hv_Mw_Channel_GetChannelNoSignalSearchStatus(VOID);

/**
 * @brief channel从no signal跳到search
 */
VOID Hv_Mw_Channel_StatusNoSignalToSearch(VOID);
#endif
