/*
 * CIPCore_DataSync.c
 *
 *  Created on: Nov 15, 2025
 *      Author: tummalanr
 */


#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/SemaphoreP.h>
#include <drivers/spinlock.h>
#include <drivers/ipc_notify.h>
#include <kernel/dpl/AddrTranslateP.h>
#include <kernel/dpl/TaskP.h>
#include "FreeRTOS.h"
#include "event_groups.h"
#include "queue.h"

#include "AppGlobal.h"
#include "CIPCoreDataSynchGlobal.h"
#include "CIPCore_DataSync.h"
#include "BoardInitExtern.h"
#include "CIPCoreExterns.h"
#include "AppExterns.h"


/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   IPC Notify Callback to Notify Messsage Received From CIP Core for System Status and Configuration
 *
 *  <!-- Parameters and return values: -->
 *  \param[in]  remoteCoreId    - RemoteCoreId from where Message Received
 *              localClientId   - Local ClientId on which Application Core is waiting for Messages from CIP Core
 *              msgValue        - CYCLICMSG_NOTIFY_ID : Cyclic Msg Received / ACYCLICMSG_NOTIFY_ID : ACyclic Msg Received
 *              crcStatus       - Not Used
 *              *args           - Not Used
 *  \return     None.
 */
void ipcnotify_msghndlr_sysstsconfig(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, int32_t crcStatus, void *args)
{
    if(remoteCoreId == CSL_CORE_ID_R5FSS0_0)
    {
        ipc_remotecoremsg rdipcMessage = {0u};
         rdipcMessage.remoteCoreId = remoteCoreId;
         rdipcMessage.localClientId = localClientId;
         rdipcMessage.remotecoremsg = msgValue;

         if(xQueueSend(ipcmsgrdreqqueue, &rdipcMessage, (TickType_t)MSGQUEUE_SEND_TO) == pdPASS)
         {
             xEventGroupSetBits(xCreatedIPCMsgEventGroup, IPCMsgEventGrp_RD_BIT);
         }
    }

    return;
}


/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   IPC Notify Callback to Notify Messsage Received From CIP Core for IO Modules
 *
 *  <!-- Parameters and return values: -->
 *  \param[in]  remoteCoreId    - RemoteCoreId from where Message Received
 *              localClientId   - Local ClientId on which Application Core is waiting for Messages from CIP Core
 *              msgValue        - CYCLICMSG_NOTIFY_ID : Cyclic Msg Received / ACYCLICMSG_NOTIFY_ID : ACyclic Msg Received
 *              crcStatus       - Not Used
 *              *args           - Not Used
 *  \return     None.
 */
void ipcnotify_msghandler_iomodules(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, int32_t crcStatus, void *args)
{
    ipc_remotecoremsg rdipcMessage = {0u};
    rdipcMessage.remoteCoreId = remoteCoreId;
    rdipcMessage.localClientId = localClientId;
    rdipcMessage.remotecoremsg = msgValue;

    if(xQueueSend(ipcmsgrdreqqueue, &rdipcMessage, (TickType_t)MSGQUEUE_SEND_TO) == pdPASS)
    {
        xEventGroupSetBits(xCreatedIPCMsgEventGroup, IPCMsgEventGrp_RD_BIT);
    }

    return;
}

uint8_t ipxpzxflg = 0u;
/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   IPC Notify Callback to Notify Messsage Received From CIP Core for PressureZone-x (DIAGVALVE)
 *
 *  <!-- Parameters and return values: -->
 *  \param[in]  remoteCoreId    - RemoteCoreId from where Message Received
 *              localClientId   - Local ClientId on which Application Core is waiting for Messages from CIP Core
 *              msgValue        - CYCLICMSG_NOTIFY_ID : Cyclic Msg Received / ACYCLICMSG_NOTIFY_ID : ACyclic Msg Received
 *              crcStatus       - Not Used
 *              *args           - Not Used
 *  \return     None.
 */
void ipcnotify_msghandler_pzxmodules(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, int32_t crcStatus, void *args)
{
        ipc_remotecoremsg rdipcMessage = {0u};
        rdipcMessage.remoteCoreId = remoteCoreId;
        rdipcMessage.localClientId = localClientId;
        rdipcMessage.remotecoremsg = msgValue;

       if(xQueueSend(ipcmsgrdreqqueue, &rdipcMessage, (TickType_t)MSGQUEUE_SEND_TO) == pdPASS)
       {
           xEventGroupSetBits(xCreatedIPCMsgEventGroup, IPCMsgEventGrp_RD_BIT);
       }

       return;
}

/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   IPC Notify Callback to Notify Messsage Received From CIP Core for MBN info
 *
 *  <!-- Parameters and return values: -->
 *  \param[in]  remoteCoreId    - RemoteCoreId from where Message Received
 *              localClientId   - Local ClientId on which Application Core is waiting for Messages from CIP Core
 *              msgValue        - MsgId Received
 *              crcStatus       - Not Used
 *              *args           - Not Used
 *  \return     None.
 */
void ipc_notify_msg_handler_mbninfo(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, int32_t crcStatus, void *args)
{

    mbnresprecvd = msgValue;

    //xEventGroupSetBits(xCreatedMBNRespEventGroup, MBNEventGrp_RespRecvd_BIT );

    return;
}

/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *  CANFD  USDO RD Message Process Task
 *  All RD messages request  are handled
 *  <!-- Parameters and return values: -->
 *  \param[in]  args : Not used.
 *  \return     None.
 */
void  IPCMsgProcessTask(void *args)
{
    EventBits_t uxBits;
    const TickType_t xTicksToWait = Delay_Ms_Ticks(5000u);

    #ifdef Debug_Verbose
         DebugP_log("[[CAN]%s Before IpcNotify_syncAll(SystemP_WAIT_FOREVER); [%" PRId64 " ms]\r\n",__func__,(ClockP_getTimeUsec()/1000u));
     #endif

     /* Wait for all cores to start.*/
     IpcNotify_syncAll(SystemP_WAIT_FOREVER);

     #ifdef Debug_Verbose
         DebugP_log("[[CAN]%s After IpcNotify_syncAll(SystemP_WAIT_FOREVER);[%" PRId64 " ms]\r\n",__func__,(ClockP_getTimeUsec()/1000u));
     #endif

     CIP_Synch_Done = 1u;
     xEventGroupSetBits(xAppStatusEventGroup, AppStsEvntGrpCIPSyncomplete_BIT);


    xEventGroupClearBits(xCreatedIPCMsgEventGroup, IPCMsgEventGrp_RD_BIT | IPCMsgEventGrp_WR_BIT);

        for(;;)
        {
            /* Wait a maximum of 5000ms for either bit 0 to be set within the event group. Clear the bits before exiting.*/
            uxBits = xEventGroupWaitBits(
                        xCreatedIPCMsgEventGroup,                           /* The event group being tested. */
                        IPCMsgEventGrp_RD_BIT | IPCMsgEventGrp_WR_BIT,      /* The bits within the event group to wait for. */
                        pdFALSE,                                            /* BIT_0 / 1should be cleared before returning. */
                        pdFALSE,                                            /* Don't wait for both bits, either bit will do. */
                        xTicksToWait );                                     /* Wait a maximum of 3000ms for either bit to be set. */

            /*Process msg received from Remote core.*/
            if( ( uxBits & IPCMsgEventGrp_RD_BIT ) != 0u )
            {
                /*check if there is space in resp verify queue.*/
                if (uxQueueMessagesWaiting(ipcmsgrdreqqueue) != 0u)
                {
                    ipc_remotecoremsg rdipcMessage = {0u};
                    if( xQueueReceive(ipcmsgrdreqqueue, &(rdipcMessage), (TickType_t)MSGQUEUE_RECV_TO) == pdTRUE)
                    {
                        #ifdef Debug_Verbose
                            //acyclic_rdstart = (ClockP_getTimeUsec()/1000u);
                            DebugP_log("[CAN CORE] %s  Msg [%#x]  remoteCoreId[%d] rdipcMessage.localClientId[%d] [%" PRId64 " ms]\r\n",__func__,rdipcMessage.remotecoremsg,rdipcMessage.remoteCoreId,rdipcMessage.localClientId,(ClockP_getTimeUsec()/1000u));
                        #endif

                    }//if(xQueueReceive(ipcmsgrdreqqueue, &(rdipcMessage), (TickType_t)MSGQUEUE_RECV_TO) )

                    if (uxQueueMessagesWaiting(ipcmsgrdreqqueue) == 0u)
                    {
                        xEventGroupClearBits(xCreatedIPCMsgEventGroup, IPCMsgEventGrp_RD_BIT);
                    }

                }//if (uxQueueMessagesWaiting(ipcmsgrdreqqueue) != 0u)

            }//if( ( uxBits & IPCMsgEventGrp_RD_BIT ) != 0u )

        }//for(;;)
}

/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   Data Sync With CIP Core IPC Process Initialization
 *
 *  <!-- Parameters and return values: -->
 *  \param[in] : None
 *  \return    : RET_OK - On success, Others - On failure.
 */
AppRET_T CIPDataSync_IPCProcessInit(void)
{
        int32_t             status;

        /*Create the event / task for Processing IPCnotify Msg from Remote cores.*/
        xCreatedIPCMsgEventGroup = xEventGroupCreate();
        if( xCreatedIPCMsgEventGroup == NULL )
        {
           /*The event group was not created because there was insufficient FreeRTOS heap available.*/
           #ifdef Debug_Verbose
               DebugP_log("xCreatedIPCMsgEventGroup Create Error !!!\r\n");
           #endif

           return AppIPC_MsgEventGrpCreateErr;
        }


        /*Create the MessageQueue for RD / WR Processing IPCnotify Msg from Remote cores.*/
        ipcmsgwrreqqueue  = xQueueCreate(MAXIPCRDWRMSGQLEN, sizeof(ipc_remotecoremsg));     /*queue length = item size = sizeof(ipc_remotecoremsg) 500 bytes.*/
        ipcmsgrdreqqueue  = xQueueCreate(MAXIPCRDWRMSGQLEN, sizeof(ipc_remotecoremsg));     /*queue length = item size = sizeof(ipc_remotecoremsg) 500 bytes.*/


        /*System Configuartion and status CallBack Registration for notifying messages Received from CIP.*/
        status = IpcNotify_registerClient(SysStatusConfig_IPC_ClientId, &ipcnotify_msghndlr_sysstsconfig, NULL);
        DebugP_assert(status==SystemP_SUCCESS);

        /*IO Modules CallBack Registration for notifying messages Received from CIP.*/
        status = IpcNotify_registerClient(IOModules_IPC_ClientId, &ipcnotify_msghandler_iomodules, NULL);
        DebugP_assert(status==SystemP_SUCCESS);

        /*PZ-x (Station Output) Modules CallBack Registration for notifying messages Received from CIP.*/
        status = IpcNotify_registerClient(PZxModules_IPC_ClientId, &ipcnotify_msghandler_pzxmodules, NULL);
        DebugP_assert(status==SystemP_SUCCESS);
        //DebugP_log("IpcNotify_registerClient PZxModules_IPC_ClientId[%d] status[%d]\r\n",PZxModules_IPC_ClientId,status);

        /*MBN Data Acces Response CallBack Registration for notifying messages Received from CIP.*/
//        status = IpcNotify_registerClient(MBN_IPC_ClientId, &ipc_notify_msg_handler_mbninfo, NULL);
//        DebugP_assert(status==SystemP_SUCCESS);


        /* This task is created at NEXT priority*/
        gIPCMsgProcessTask = xTaskCreateStatic( IPCMsgProcessTask,              /* Pointer to the function that implements the task. */
                                                "IPCMsgProcessTask",            /* Text name for the task.  This is to facilitate debugging only. */
                                                IPCMsgProcess_TASK_SIZE,         /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                                NULL,                           /* We are not using the task parameter. */
                                                IPCMsgProcess_TASK_PRI,         /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                                gIPCMsgProcessTaskStack,        /* pointer to stack base */
                                                &gIPCMsgProcessTaskObj );       /* pointer to statically allocated task object memory */
         configASSERT(gIPCMsgProcessTask != NULL);

         if( gIPCMsgProcessTask == NULL ) {
                return   AppIPC_MsgProcessTaskCreateErr;
         }


        return AppRET_OK;
}


