/**
 * @file comms_uhf_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_uhf_ipc.h"
#include "exo_common.h"
#include "tc_tm_mngr.h"
#include "logger.h"
#include "exo_tctm_ipc.h"
#include "sdr_app_main.h"

extern s_sdr_tmr_cfg PLACE_IN_EXT_RAM_MEM uhf_tmr_cfg;
extern uint16_t PLACE_IN_EXT_RAM_MEM uhf_tc_tm_id;

uint32_t PLACE_IN_EXT_RAM_MEM uhf_beacon_seq_num = 0;
uint8_t PLACE_IN_EXT_RAM_MEM comms_uhf_csw_rx_buf[512] = {0};
extern uint8_t PLACE_IN_EXT_RAM_MEM uhf_radio_id;
extern uint16_t PLACE_IN_EXT_RAM_MEM uhf_tc_seq_no;


extern  volatile uint8_t PLACE_IN_EXT_RAM_MEM uhf_sch_gs_contact;
extern  s_sdr_gpass_beacon_cfg uhf_gpass_cfg;


/** Timer used for enable repition of Beacon signal */
extern os_timer_handle_ptr uhf_beacon_rep_timer;

/**
 * @brief This function handles the comms telecommand, telemetry set response
 *
 * @brief Handle set TC/TM response
 * 
 * @param msg_id Message ID
 * @param status Response status 
 * @param tc_tm_data Pointer to response data
 */
void comms_uhf_tc_tm_set_rsp_hdlr(uint16_t msg_id, int32_t status, uint8_t *tc_tm_data)
{
    uint8_t *pld = NULL;

    UNUSED(tc_tm_data);
    os_itc_msg_handle_t comms_uhf_msg;

    //Init IPC
    comms_uhf_msg.src_entity= COMMS_UHF_CTLR;

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

    pld = comms_uhf_msg.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, comms_uhf_csw_rx_buf, sizeof(uint16_t));
    os_memcpy(&pld[TM_RADIO_MOD_IDX], &comms_uhf_csw_rx_buf[TM_RADIO_MOD_IDX], 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] = 0x70;
    pld[TM_PLD_IDX] = status;

    comms_uhf_msg.Msg_id = msg_id;
    comms_uhf_msg.Msg_len = 1;

    status = os_itc_msg_send(&comms_uhf_msg,TM_STORAGE,os_send_itc_wait);

    uhf_tc_tm_id = 0;
}

/**
 * @brief This function handles the comms telecommand, telemetry response
 * @brief Handle get TM storage response
 *
 * @param msg_id Message ID 
 * @param tm_pld Pointer to TM data
 * @param size TM data size in bytes
 */
void comms_uhf_tm_stor_get_rsp_hdlr(uint16_t msg_id, uint8_t *tm_pld, uint16_t size)
{
    uint8_t *pld = NULL;

    os_itc_msg_handle_t uhf_tm_stor_ipc;             ///< COMMS state transmit message

    //Init IPC
    uhf_tm_stor_ipc.src_entity= COMMS_UHF_CTLR;

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

    pld = uhf_tm_stor_ipc.pld.pld_ptr;

    //Extract the sequence number
    os_memcpy(pld, &uhf_tc_seq_no, sizeof(uint16_t));
    os_memcpy(&pld[TM_RADIO_MOD_IDX], &uhf_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;

    uhf_tm_stor_ipc.Msg_id = msg_id;
    uhf_tm_stor_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);
    os_itc_msg_send(&uhf_tm_stor_ipc, TM_STORAGE, os_send_itc_wait);
}


/**
 * @brief This function handles the comms telecommand, telemetry get response
 * @brief Handle get TC/TM response
 *
 * @param msg_id Message ID
 * @param status Response status code
 * @param tc_tm_data Pointer to response data
 * @param size Response data size in bytes
 */
void comms_uhf_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_uhf_msg;

    //Init IPC
    comms_uhf_msg.src_entity= COMMS_UHF_CTLR;

    //Extract the sequence number
    os_memcpy(comms_uhf_csw_rx_buf, tc_tm_data, sizeof(uint16_t));
    os_memcpy(&comms_uhf_csw_rx_buf[TM_RADIO_MOD_IDX], &tc_tm_data[TC_RADIO_MOD_IDX], 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
     */
    comms_uhf_csw_rx_buf[TM_CTRL_DATA_IDX] =0x70;
    comms_uhf_msg.Msg_id = msg_id;
    comms_uhf_msg.Msg_len = size;

    comms_uhf_msg.pld.pld_ptr = (uint8_t *)os_malloc(size + 5);
    os_memcpy(comms_uhf_msg.pld.pld_ptr,comms_uhf_csw_rx_buf, size+4);

    status = os_itc_msg_send(&comms_uhf_msg, TM_STORAGE, os_send_itc_wait);

    uhf_tc_tm_id = 0;
}

/**
 * @brief This function handles the comms telecommand, telemetry response
  * @brief Handle generic TC/TM response
 * 
 * @param msg_id Message ID
 * @param size Response data size in bytes 
*/
void comms_uhf_tc_tm_rsp_hdlr(uint16_t msg_id, uint16_t size)
{
    os_itc_msg_handle_t comms_uhf_msg;

    //Init IPC
    comms_uhf_msg.src_entity= COMMS_UHF_CTLR;

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

    DEBUG_CPRINT(("\n\r[UHF] TM size %d",size));
    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,UHF_TM_SIZE__u32_,size);
    comms_uhf_msg.pld.pld_ptr = (uint8_t *)os_malloc(size + 5);
    os_memcpy(comms_uhf_msg.pld.pld_ptr,comms_uhf_csw_rx_buf, size+4);

    os_itc_msg_send(&comms_uhf_msg, TM_STORAGE, os_send_itc_wait);

    uhf_tc_tm_id = 0;
}

/**
 * @brief Abstracted API for COMMS layer that sends message payload
 *   to destination thread using os IPC functionalities
 *
 * @brief Send an IPC message over the UHF radio 
 * 
 * This function sends an IPC message with the given message ID 
 * to the specified destination address over the UHF radio.
 * 
 * @param[in] msg_id Message ID to send
 * @param[in] dest Destination address for the message
 */
void uhf_send_ipc(uint16_t msg_id, uint16_t dest)
{
    os_itc_msg_handle_t comms_uhf_msg;
    comms_uhf_msg.Msg_id = msg_id;
    comms_uhf_msg.src_entity = COMMS_UHF_CTLR;

    comms_uhf_msg.pld.pld_ptr = NULL;

    os_itc_msg_send(&comms_uhf_msg, dest, os_send_itc_wait);
}

/**
 * @brief This API for UHF layer that sends message payload
 * to destination thread using os IPC functionalities
 * @brief Send IPC payload over UHF
 *
 * @param msg_id Message ID
 * @param dest Destination module ID
 * @param pld_size Payload size in bytes
 * @param pld_ptr Pointer to payload data
 */
void uhf_send_ipc_pld(uint16_t msg_id, uint16_t dest, uint16_t pld_size, uint8_t *pld_ptr)
{
    os_itc_msg_handle_t comms_uhf_msg;
    comms_uhf_msg.Msg_id = msg_id;
    comms_uhf_msg.src_entity = COMMS_UHF_CTLR;

    comms_uhf_msg.pld.pld_ptr = (uint8_t *)os_malloc(pld_size);

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

    os_itc_msg_send(&comms_uhf_msg, dest, os_send_itc_wait);
}

/**
 * @brief This function handles the comms telecommand, telemetry get response
 * @brief Transmit UHF beacon
 * 
 * @param beacon_data Pointer to beacon data 
 * @param size Length of beacon data in bytes
 */
void comms_uhf_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_uhf_msg;

    uhf_beacon_seq_num++;

    //Init IPC
    comms_uhf_msg.src_entity= COMMS_UHF_CTLR;

    comms_uhf_msg.Msg_id = TC_COMMS_UHF_BEACON_DATA;
    comms_uhf_msg.Msg_len = size;

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

    pld = comms_uhf_msg.pld.pld_ptr;


    //Extract the sequence number
    os_memcpy(pld,&uhf_beacon_seq_num, sizeof(uint32_t));
    pld[TM_RADIO_MOD_IDX] = COMMS_UHF;
    DEBUG_CPRINT(("\nUHF BEACON PLD SEND\n"));
    /*
     * 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);

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

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

        if (tm_size>0)
        {
            // send to s-band
            tm_store_local_msg.Msg_id = comms_uhf_msg.Msg_id;
            tm_store_local_msg.pld_info = COMMS_UHF;
            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_UHF_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_uhf_msg.pld.pld_ptr);
    }
if((uhf_gpass_cfg.gpass_beacon_tx_enb)&&(uhf_sch_gs_contact))
    {
        os_timer_start(uhf_beacon_rep_timer,uhf_gpass_cfg.beacon_tx_interval);
    }
    else
    {
        if(uhf_tmr_cfg.tx_data_rep_cnt)
        {   
            os_timer_start(uhf_beacon_rep_timer,uhf_tmr_cfg.beacon_rep_tmr);
        }
    }
}
