/**
 * @file comms_ipc.c
 *
 * @brief This file has the functions related to IPC message encode/decode
 *        for IPCs to communicate with TC-TM manager, OBC and other SW layers
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
/*********************************************************************/
#include "comms_ipc.h"
#include "exo_common.h"
#include "logger.h"
#include "tc_tm_mngr.h"
#include "exo_tctm_ipc.h"
#include "sdr_app_main.h"

#define TM_HEADER_OVERHEAD         (128) ///< TM header overhead size

uint32_t PLACE_IN_EXT_RAM_MEM sband_beacon_seq_num = 0; ///< S-band beacon sequence number
uint8_t PLACE_IN_EXT_RAM_MEM comms_csw_rx_buf[512] = {0}; ///< CSW RX buffer
extern uint8_t PLACE_IN_EXT_RAM_MEM sband_radio_id ; ///< S-band radio ID
extern uint16_t PLACE_IN_EXT_RAM_MEM sband_tc_seq_no; ///< S-band TC sequence number
extern uint16_t PLACE_IN_EXT_RAM_MEM sband_tc_tm_id; ///< S-band TC/TM message ID
extern s_sdr_tmr_cfg PLACE_IN_EXT_RAM_MEM sband_tmr_cfg;

volatile uint8_t PLACE_IN_EXT_RAM_MEM sband_sch_gs_contact;
extern  s_sdr_gpass_beacon_cfg sband_gpass_cfg;




/** Timer used for enable and periodic transmission of Beacon signal */
extern os_timer_handle_ptr sband_beacon_rep_timer;

/**
 * @brief This function handles the comms telecommand, telemetry set response
 * @brief Set callback function for TC/TM response handling.
 * 
 * This function sets the callback function to handle responses 
 * for a specific TC/TM message ID. The callback will be invoked
 * when a response is received from the radio module for the 
 * message ID.
 * 
 * @param msg_id TC/TM message ID to set callback for
 * @param status Status in response 
 * @param tc_tm_data Pointer to response data
 */
void comms_tc_tm_set_rsp_hdlr(uint16_t msg_id, int32_t status, uint8_t *tc_tm_data)
{
    uint8_t *pld = NULL;

    os_itc_msg_handle_t comms_csw_trans_msg;

    //Init IPC
    comms_csw_trans_msg.src_entity= COMMS_SBAND_CTLR;

    comms_csw_trans_msg.pld.pld_ptr = (uint8_t *)os_malloc(5);

    pld = comms_csw_trans_msg.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, tc_tm_data, sizeof(uint16_t));

    /*
     * Append the TM_CTRL data. 0x70 represents enable
     * encryption, authentication and message type as
     * response. Refer TC/TM manager document for more
     * information
     */
    pld[2] = 0x70;
    os_memcpy(&pld[TM_RADIO_MOD_IDX], &tc_tm_data[TC_RADIO_MOD_IDX], sizeof(uint8_t));
    pld[TM_PLD_IDX] = status;

    DEBUG_CPRINT(("\nCOMMS Radio ID TC: %d, TM: %d\n",tc_tm_data[TC_RADIO_MOD_IDX],pld[TM_RADIO_MOD_IDX]));
    log_id_with_two_arg(LOG_INFO_L1,LOG_COMMS,COMMS_RADIO_ID_TC__u8_TM__u8_,tc_tm_data[TC_RADIO_MOD_IDX],pld[TM_RADIO_MOD_IDX]);
    comms_csw_trans_msg.Msg_id = msg_id;
    comms_csw_trans_msg.Msg_len = 1;

    status = os_itc_msg_send(&comms_csw_trans_msg,TM_STORAGE,os_send_itc_wait);
}

/**
 * @brief This function handles the comms telecommand, telemetry get response
 * 
 * This function gets the callback function previously set to handle
 * responses for a specific TC/TM message ID. 
 * 
 * @param msg_id TC/TM message ID to get callback for  
 * @param status Status in response
 * @param tc_tm_data Pointer to response data 
 * @param size Size of response data
 */
void comms_tc_tm_get_rsp_hdlr(uint16_t msg_id,int32_t status, uint8_t *tc_tm_data, uint16_t size)
{
    os_itc_msg_handle_t comms_csw_trans_msg;

    //Init IPC
    comms_csw_trans_msg.src_entity= COMMS_SBAND_CTLR;

    //Extract the sequence number
    os_memcpy(comms_csw_rx_buf, tc_tm_data, sizeof(uint16_t));

    /*
     * Append the TM_CTRL data. 0x70 represents enable
     * encryption, authentication and message type as
     * response. Refer TC/TM manager document for more
     * information
     */
    comms_csw_rx_buf[2] =0x70;
    os_memcpy(&comms_csw_rx_buf[TM_RADIO_MOD_IDX], &tc_tm_data[TC_RADIO_MOD_IDX], sizeof(uint8_t));
    comms_csw_trans_msg.Msg_id = msg_id;
    comms_csw_trans_msg.Msg_len = size;

    DEBUG_CPRINT(("\nCOMMS Radio ID TC: %d, TM: %d\n",tc_tm_data[TC_RADIO_MOD_IDX],comms_csw_rx_buf[TM_RADIO_MOD_IDX]));
    log_id_with_two_arg(LOG_INFO_L1,LOG_COMMS,COMMS_RADIO_ID_TC__u8_TM__u8_,tc_tm_data[TC_RADIO_MOD_IDX],comms_csw_rx_buf[TM_RADIO_MOD_IDX]);
    comms_csw_trans_msg.pld.pld_ptr = (uint8_t *)os_malloc(size + 5);
    os_memcpy(comms_csw_trans_msg.pld.pld_ptr,comms_csw_rx_buf, size+4);

    status = os_itc_msg_send(&comms_csw_trans_msg, TM_STORAGE, os_send_itc_wait);
}

/**
 * @brief Abstracted API for COMMS layer that sends message payload
 *   to destination thread using os IPC functionalities
 *
 * @brief Send IPC message without payload.
 * 
 * This function sends an IPC message without payload
 * to destination thread using os IPC functionalities
 * 
 * @param msg_id IPC message ID 
 * @param dest Destination thread ID
 */
void sband_send_ipc(uint16_t msg_id, uint16_t dest)
{
    os_itc_msg_handle_t comms_csw_trans_msg;
    comms_csw_trans_msg.Msg_id = msg_id;
    comms_csw_trans_msg.src_entity = COMMS_SBAND_CTLR;

    comms_csw_trans_msg.pld.pld_ptr = NULL;

    os_itc_msg_send(&comms_csw_trans_msg, dest, os_send_itc_wait);
}

/**
 * @brief This API for SBAND layer that sends message payload
 * to destination thread using os IPC functionalities
 * @brief Send IPC message with payload.
 *
 * This function sends an IPC message with payload
 * to destination thread using os IPC functionalities
 * 
 * @param msg_id IPC message ID
 * @param dest Destination thread ID 
 * @param pld_size Payload size in bytes
 * @param pld_ptr Pointer to payload data
 */
void sband_send_ipc_pld(uint16_t msg_id, uint16_t dest, uint16_t pld_size, uint8_t *pld_ptr)
{
    os_itc_msg_handle_t comms_csw_trans_msg;
    comms_csw_trans_msg.Msg_id = msg_id;
    comms_csw_trans_msg.src_entity = COMMS_SBAND_CTLR;
    comms_csw_trans_msg.Msg_len = pld_size;
    comms_csw_trans_msg.pld.pld_ptr = (uint8_t *)os_malloc(pld_size);

    os_memcpy(comms_csw_trans_msg.pld.pld_ptr,pld_ptr, pld_size);

    os_itc_msg_send(&comms_csw_trans_msg, dest, os_send_itc_wait);
}

/**
 * @brief This function handles the sband telecommand, telemetry set response
 *
 * This function sets the callback function to handle responses 
 * for a specific S-band TC/TM message ID. The callback will be invoked
 * when a response is received from the S-band radio module.
 *  
 * @param msg_id TC/TM message ID 
 * @param status Status in response
*/
void sband_tc_tm_set_rsp_hdlr(uint16_t msg_id, int32_t status)
{
    uint8_t *pld = NULL;

    os_itc_msg_handle_t sband_ipc;             ///< COMMS state transmit message

    //Init IPC
    sband_ipc.src_entity= COMMS_SBAND_CTLR;

    sband_ipc.pld.pld_ptr = (uint8_t *)os_malloc(5);

    pld = sband_ipc.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, &sband_tc_seq_no, sizeof(uint16_t));
    os_memcpy(&pld[TM_RADIO_MOD_IDX], &sband_radio_id, sizeof(uint8_t));

    /*
     * Append the TM_CTRL data. 0x70 represents enable
     * encryption, authentication and message type as
     * response. Refer TC/TM manager document for more
     * information
     */
    pld[TM_CTRL_DATA_IDX] = TM_DEFAULT_CTRL_DATA;
    pld[TM_PLD_IDX] = status;

    sband_ipc.Msg_id = msg_id;
    sband_ipc.Msg_len = 1;

    DEBUG_CPRINT(("[SBAND] TM response sent"));
    log_id(LOG_INFO_L1,LOG_COMMS,__SBAND__TM_RESPONSE_SENT);
    status = os_itc_msg_send(&sband_ipc,TM_STORAGE,os_send_itc_wait);
}

/**
 * @brief This function handles the sband telecommand, telemetry get response
 * @brief Get callback function for S-band TC/TM response.
 * 
 * This function gets the callback function previously set to handle
 * responses for a specific S-band TC/TM message ID.
 *
 * @param msg_id TC/TM message ID  
 * @param status Status in response
 * @param size Size of response data  
 * @param tm_pld Pointer to response data
 */
void sband_tc_tm_get_rsp_hdlr(uint16_t msg_id,int32_t status, uint16_t size, uint8_t *tm_pld)
{
    uint8_t *pld = NULL;

    os_itc_msg_handle_t sband_ipc;             ///< COMMS state transmit message

    //Init IPC
    sband_tc_tm_id = 0;
    sband_ipc.src_entity= COMMS_SBAND_CTLR;

    sband_ipc.pld.pld_ptr = (uint8_t *)os_malloc_eram(size + 5);

    pld = sband_ipc.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, &sband_tc_seq_no, sizeof(uint16_t));
    os_memcpy(&pld[TM_RADIO_MOD_IDX], &sband_radio_id, sizeof(uint8_t));

    /*
     * Append the TM_CTRL data. 0x70 represents enable
     * encryption, authentication and message type as
     * response. Refer TC/TM manager document for more
     * information
     */
    pld[TM_CTRL_DATA_IDX] = TM_DEFAULT_CTRL_DATA;
    sband_ipc.Msg_id = msg_id;
    sband_ipc.Msg_len = size;

    os_memcpy(&pld[TM_PLD_IDX],tm_pld, size);

    DEBUG_CPRINT(("[SBAND] TM pld response sent"));
    log_id(LOG_INFO_L1,LOG_COMMS,__SBAND__TM_PLD_RESPONSE_SENT);
    status = os_itc_msg_send(&sband_ipc, TM_STORAGE, os_send_itc_wait);
}

/**
 * @brief This function handles the comms telecommand, telemetry get response
 * @brief Send S-band beacon data over IPC.
 * 
 * This function sends the beacon data over IPC to the 
 * S-band TX thread for transmission.
 *
 * @param beacon_data Pointer to beacon data  
 * @param size Size of beacon data in bytes 
 */
void comms_sband_beacon_tx(uint8_t *beacon_data, uint16_t size)
{
	int32 tm_size = -1;

	uint8_t *pld = NULL;

	uint8 *tm_storage_data;

	os_itc_msg_handle_t tm_store_local_msg;
    os_itc_msg_handle_t comms_sband_msg;

    sband_beacon_seq_num++;

    //Init IPC
    comms_sband_msg.src_entity= COMMS_SBAND_CTLR;

    comms_sband_msg.Msg_id = TM_COMMS_BEACON_TX;
    comms_sband_msg.Msg_len = size;

    comms_sband_msg.pld.pld_ptr = (uint8_t *)os_malloc(size + 5);

    pld = comms_sband_msg.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, &sband_beacon_seq_num, sizeof(uint16_t));
    pld[TM_RADIO_MOD_IDX] = COMMS_SBAND_IQS;


    /*
     * Append the TM_CTRL data. 0x70 represents enable
     * encryption, authentication and message type as
     * response. Refer TC/TM manager document for more
     * information
     */
    pld[TM_CTRL_DATA_IDX] =0x70;
    os_memcpy(&pld[TM_PLD_IDX], beacon_data, size);

    DEBUG_CPRINT(("****SBAND BEACON PLD SENT*****"));

    /** TBD: extra allocation were done, need to check, TM Headers might be around 40 bytes */
    tm_storage_data = (uint8*) os_malloc_eram(comms_sband_msg.Msg_len+TM_HEADER_OVERHEAD);

    if(tm_storage_data)
    {
        //Add tc/tm headers with the telemetry data
        tm_size = handle_tm_data(&comms_sband_msg,
                tm_storage_data);

        if (tm_size>0)
        {
            // send to s-band
            tm_store_local_msg.Msg_id = comms_sband_msg.Msg_id;
            tm_store_local_msg.pld_info = COMMS_SBAND_IQS;
            tm_store_local_msg.src_entity = TM_STORAGE;
            tm_store_local_msg.pld.pld_ptr = tm_storage_data;
            tm_store_local_msg.Msg_len = tm_size;
            os_itc_msg_send(&tm_store_local_msg, COMMS_SBAND_TX,os_send_itc_wait);
        }
        else
        {
            DEBUG_CPRINT((" hello TM Packing failed \n"));
            log_id(LOG_ERROR,LOG_COMMS,HELLO_TM_PACKING_FAILD);
            if(tm_storage_data)
            {
                os_free(tm_storage_data);
                tm_storage_data = NULL;
            }
        }
        os_free(comms_sband_msg.pld.pld_ptr);
    }
    /*condition check for beacon tx enable timer start option*/
    if((sband_gpass_cfg.gpass_beacon_tx_enb)&&(sband_sch_gs_contact))
    {
        os_timer_start(sband_beacon_rep_timer,sband_gpass_cfg.beacon_tx_interval);
    }
    else
    {
        if(sband_tmr_cfg.tx_data_rep_cnt)
        {
            os_timer_start(sband_beacon_rep_timer,sband_tmr_cfg.beacon_rep_tmr); 
        }
    }
}

