/**
 * @file sdr_app_intf.c
 *
 * @brief This file has the SDR Application thread functions and other main functions for S-Band control
 *
 * @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<stdio.h>
#include<stdint.h>
#include "sdr_app_intf.h"
#include "sdr_app_ipc.h"
#include "sdr_app_main.h"
#include "exo_common.h"
#include "comms_csw.h"
#include "comms_uhf_main.h"
#include "exo_tctm_ipc.h"
#include "logger.h"

uint8_t PLACE_IN_EXT_RAM_MEM num_sdr;///< Number of SDRs configured

uint8_t radio_id_dest_map[MAX_SDR_CFG] = {0xFF,COMMS_SBAND_CTLR,COMMS_UHF_CTLR,COMMS_SBAND_CTLR,0xFF};

s_sdr_cfg PLACE_IN_EXT_RAM_MEM sdr_app_cfg[MAX_SDR_CFG];///< SDR configuration array
s_sdr_tmr_cfg PLACE_IN_EXT_RAM_MEM sdr_tmr[MAX_SDR_CFG];///< SDR timer configuration array 
s_sdr_rssi_cfg PLACE_IN_EXT_RAM_MEM sdr_rssi_cfg[MAX_SDR_CFG];///< SDR RSSI configuration array
s_sdr_tm_cfg PLACE_IN_EXT_RAM_MEM sdr_tm_cfg[MAX_SDR_CFG];///< SDR telemetry configuration array
s_sdr_sens_cfg PLACE_IN_EXT_RAM_MEM sdr_sens_cfg[MAX_SDR_CFG];///< SDR sensitivity configuration array
static s_tctm_rm_overrule sdr_radio_id_overrule;
s_sdr_gpass_beacon_cfg sdr_gpass_cfg[MAX_SDR_CFG];


/**
 * @brief Set SDR configuration
 * 
 * This function handles setting the configuration for an SDR based on 
 * payload data received. It parses the payload to get the SDR ID and
 * configuration struct, saves the config to the appropriate array index,
 * and sends the config to the SDR controller if valid.
 *
 * @param[in] pld Pointer to payload data containing SDR ID and config struct
 * @return Result code indicating success or failure of operation
*/  
int8_t sdr_app_tc_set_sdr_cfg(uint8_t *pld)
{
    int8_t ret =0;
    uint8_t num_sdr_idx = 0;
    uint8_t radio_id=0;

   s_sdr_cfg *sdr_cfg= NULL;

    os_memcpy(&num_sdr,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("\nNUM_SDR: %d\n",num_sdr));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,NUM_SDR__u8_,num_sdr);

    pld = pld + sizeof(uint8_t);

    for(num_sdr_idx=0;num_sdr_idx<num_sdr;num_sdr_idx ++)
    {
        sdr_cfg=(s_sdr_cfg *)&pld[(sizeof(s_sdr_cfg)-1)*num_sdr_idx];
        radio_id = sdr_cfg->radio_id;
        os_memcpy(&sdr_app_cfg[radio_id],sdr_cfg,sizeof(s_sdr_cfg));
        DEBUG_CPRINT(("SDR_DEST: %d",sdr_app_cfg[radio_id].radio_id));
        if(0xFF != radio_id_dest_map[sdr_app_cfg[radio_id].radio_id] )
        {
            sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_SDR_CFG_REQ,radio_id_dest_map[sdr_app_cfg[radio_id].radio_id],sizeof(s_sdr_cfg),(uint8_t *)&sdr_app_cfg[radio_id]);
        }

    }

    ret = SDR_APP_SUCCESS;

    return ret;

}

/**
 * @brief Set SDR status 
 *
 * This function sets the active status for the specified SDR. It parses
 * the input payload to get the SDR ID and new status value, updates the 
 * status in the SDR app config array, and sends a request to the SDR
 * controller to update the active status if required.
 *
 * @param[in] pld Pointer to payload data containing SDR ID and new status
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_set_sdr_sts(uint8_t *pld)
{
    int8_t ret =0;
    uint8_t radio_id = 0;
    uint8_t sdr_sts = 0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_sts,(pld + sizeof(uint8_t)),sizeof(uint8_t));

    DEBUG_CPRINT(("Radio ID:%d SDR Status :%d",radio_id,sdr_sts));
    log_id_with_two_arg(LOG_INFO_L1,LOG_COMMS,RADIO_ID__u8__SDR_STATUS__u8_,radio_id,sdr_sts);

    DEBUG_CPRINT((" SET SDRR: %d\n",sdr_app_cfg[radio_id].sdr_sts));

    if(sdr_sts == sdr_app_cfg[radio_id].sdr_sts)
    {
    	/** Nothing to be done */
    	ret = SDR_APP_NO_ACTION;
    }
    else
    {
        sdr_app_cfg[radio_id].sdr_sts = sdr_sts; //TODO:SDR CONTROLER handshake based on actual sdr status

        DEBUG_CPRINT((" SET SDRR: %d\n",sdr_app_cfg[radio_id].sdr_sts));

        if(0xFF != radio_id_dest_map[radio_id] )
        {
             sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_MODE_CFG_REQ,radio_id_dest_map[radio_id],sizeof(sdr_sts),&sdr_sts);
        }
#if 0
        switch(sdr_sts)
        {
            case SDR_NOT_PRESENT:
                {
                }
                break;
            case SDR_PRESENT:
                {
                }
                break;
            case SDR_CONFIGURED_INACTIVE:
                {
                }
                break;
            case SDR_CONFIGURED_ACTIVE_RX:
                {
                }
                break;
            case SDR_CONFIGURED_ACTIVE_TX:
                {
                }
                break;
            case SDR_CONFIGURED_ACTIVE:
                {
                }
                break;
            default:
                {
                }
                break;
        }
#endif
    }
    return ret;
}


/**
 * @brief Set SDR timer configuration  
 *
 * This function handles setting the timer configuration for an SDR.
 * It parses the input payload to get the SDR ID and timer config struct,
 * saves the timer config to the appropriate index in the timer config
 * array, and sends the config to the SDR controller if valid.
 * 
 * @param[in] pld Pointer to payload data with SDR ID and timer config
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_set_sdr_tmr_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_tmr[radio_id],(pld + sizeof(uint8_t)),sizeof(s_sdr_tmr_cfg));

    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    if(0xFF != radio_id_dest_map[radio_id] )
    {
         sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_TMR_CFG_REQ,radio_id_dest_map[radio_id],sizeof(s_sdr_tmr_cfg),(uint8_t *)&sdr_tmr[radio_id]);
    }

    ret = SDR_SET_TMR_SUCCESS;

    return ret;
}


int8_t sdr_app_tc_set_sdr_sch_beacon_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret=0;
    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_gpass_cfg[radio_id],pld,sizeof(s_sdr_gpass_beacon_cfg));

    if(0xFF != radio_id_dest_map[radio_id]) 
    {
         sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_GPASS_CFG,radio_id_dest_map[radio_id],sizeof(s_sdr_gpass_beacon_cfg),(uint8_t *)&sdr_gpass_cfg[radio_id]);

    }
    ret = SDR_SET_GPASS_SUCCESS;
    return ret;
}

int8_t sdr_app_tc_get_sdr_sch_beacon_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_GET_GPASS_SUCCESS;

   sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_SCH_BEACON_CFG, ret, sizeof(s_sdr_gpass_beacon_cfg),(uint8_t *)&sdr_gpass_cfg[radio_id]);

    return ret;
}


/** 
 * @brief Set SDR RX RSSI configuration
 *
 * This function sets the RSSI configuration for an SDR receiver.
 * It parses the payload to get the SDR ID and RSSI config struct,
 * saves the config to the RSSI array, and sends to the SDR controller.
 *
 * @param[in] pld Pointer to payload data with SDR ID and RSSI config
 * @return Result code indicating success or failure of operation 
*/
int8_t sdr_app_tc_set_sdr_rx_rssi_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_rssi_cfg[radio_id],(pld + sizeof(uint8_t)),sizeof(s_sdr_rssi_cfg));

    if(0xFF != radio_id_dest_map[radio_id] )
    {
         sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_RSSI_CFG_REQ,radio_id_dest_map[radio_id],sizeof(s_sdr_rssi_cfg),(uint8_t *)&sdr_rssi_cfg[radio_id]);
    }

    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_RX_RSSI_SUCCESS;
    return ret;

}

/**
 * @brief Set SDR telemetry configuration
 *
 * This function handles setting the telemetry configuration for an 
 * SDR. It parses the payload to get the SDR ID and telemetry config
 * struct, saves the config to the telemetry array, and sends to the
 * SDR controller if valid.
 *
 * @param[in] pld Pointer to payload data with SDR ID and telemetry config
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_set_sdr_tm_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_tm_cfg[radio_id],(pld+ sizeof(uint8_t)),sizeof(s_sdr_tm_cfg));

    if(0xFF != radio_id_dest_map[radio_id] )
    {
         sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_TM_CFG_REQ,radio_id_dest_map[radio_id],sizeof(sdr_tm_cfg),(uint8_t *)&sdr_tm_cfg[radio_id]);
    }

     DEBUG_CPRINT(("Radio ID:%d ",radio_id));
     ret = SDR_SET_TM_SUCCESS;
    return ret;
}

/**
 * @brief Set SDR sensitivity configuration
 * 
 * This function sets the sensitivity configuration for an SDR. It parses
 * the payload to get the SDR ID and sensitivity config struct, saves the
 * config to the sensitivity array, and sends to the SDR controller. 
 *
 * @param[in] pld Pointer to payload with SDR ID and sensitivity config
 * @return Result code indicating success or failure of operation  
*/
int8_t sdr_app_tc_set_sdr_sens_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    os_memcpy(&sdr_sens_cfg[radio_id],(pld+ sizeof(uint8_t)),sizeof(s_sdr_sens_cfg));

    if(0xFF != radio_id_dest_map[radio_id] )
    {
         sdr_app_send_ipc_pld(SDR_APP_SDR_CTRL_SENS_CFG_REQ,radio_id_dest_map[radio_id],sizeof(sdr_sens_cfg),(uint8_t *)&sdr_sens_cfg[radio_id]);
    }

     DEBUG_CPRINT(("Radio ID:%d ",radio_id));
     ret = SDR_SET_SENS_SUCCESS;
    return ret;
}

int8_t sdr_app_tc_set_over_rule_cfg(uint8_t *pld)
{
    int8_t ret =0;
    s_tctm_rm_overrule *tctm_overrule;
    tctm_overrule = os_malloc(sizeof(s_tctm_rm_overrule));
    if(tctm_overrule == NULL)
    {
       ret = SDR_SET_OVER_RULE_FAIL; 
    }
    else
    {
    os_memcpy(tctm_overrule,pld,sizeof(s_tctm_rm_overrule));
    os_memcpy(&sdr_radio_id_overrule,pld,sizeof(s_tctm_rm_overrule));
    sdr_app_send_ipc_pld(SDR_RADIO_ID_OVR_RULE_CFG,TM_STORAGE,sizeof(s_tctm_rm_overrule),(uint8_t *)tctm_overrule);

    ret = SDR_SET_OVER_RULE_SUCCESS;
    }

    return ret;
}

int8_t sdr_app_tc_get_over_rule_cfg(uint8_t *pld)
{
    int8_t ret =0;
    ret = SDR_GET_OVER_RULE_SUCCESS;

    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_OVER_RULE_CFG, ret, sizeof(s_tctm_rm_overrule),(uint8_t *)&sdr_radio_id_overrule);
    return ret;
}
/**
 * @brief Get SDR configuration
 *
 * This function handles getting the configuration for the specified SDR.
 * It parses the payload to get the SDR ID, retrieves the config from 
 * the SDR config array, and sends it in the response to the caller.
 * 
 * @param[in] pld Pointer to payload data with SDR ID 
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_get_sdr_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret =  SDR_GET_CFG_SUCCESS;

    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_CFG, ret, sizeof(s_sdr_cfg),(uint8_t *)&sdr_app_cfg[radio_id]);
    return ret;
}

/**
 * @brief Get SDR status
 *
 * This function gets the current status of the specified SDR. It parses
 * the payload to get the SDR ID, retrieves the status from the SDR app 
 * config array, and sends it in the response to the caller.
 *
 * @param[in] pld Pointer to payload data with SDR ID
 * @return Result code indicating success or failure of operation  
*/
int8_t sdr_app_tc_get_sdr_sts(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));

    ret = SDR_GET_STS_SUCCESS;
   
    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_STS, ret, sizeof(e_sdr_sts),(uint8_t *)&sdr_app_cfg[radio_id].sdr_sts );

    DEBUG_CPRINT((" GET SDRR: %d\n",sdr_app_cfg[radio_id].sdr_sts));
    return ret;
}

/**
 * @brief Get SDR timer configuration
 * 
 * This function handles getting the timer configuration for the 
 * specified SDR. It parses the payload to get the SDR ID, retrieves 
 * the timer config from the timer config array, and sends it in the 
 * response to the caller.
 *
 * @param[in] pld Pointer to payload data with SDR ID
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_get_sdr_tmr_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_GET_TMR_SUCCESS;

   sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_TMR_CFG, ret, sizeof(s_sdr_tmr_cfg),(uint8_t *)&sdr_tmr[radio_id]);

    return ret;
}

/**
 * @brief Get SDR RX RSSI configuration 
 *
 * This function gets the RSSI configuration for the specified SDR 
 * receiver. It parses the payload to get the SDR ID, retrieves the
 * RSSI config from the array, and sends it in the response.
 * 
 * @param[in] pld Pointer to payload data with SDR ID  
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_get_sdr_rx_rssi_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_GET_RX_RSSI_SUCCESS;

    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_RX_RSSI_CFG, ret, sizeof(s_sdr_rssi_cfg),(uint8_t *)&sdr_rssi_cfg[radio_id]);

    return ret;
}

/**
 * @brief Get SDR telemetry configuration
 *
 * This function handles getting the telemetry configuration for the
 * specified SDR. It parses the payload to get the SDR ID, retrieves 
 * the telemetry config from the array, and sends it in the response.
 *
 * @param[in] pld Pointer to payload data with SDR ID
 * @return Result code indicating success or failure of operation 
*/ 
int8_t sdr_app_tc_get_sdr_tm_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_GET_TM_SUCCESS;

    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_TM_CFG, ret, sizeof(sdr_tm_cfg),(uint8_t *)&sdr_tm_cfg[radio_id]);

    return ret;
}

/**
 * @brief Get SDR sensitivity configuration
 *
 * This function gets the sensitivity configuration for the specified
 * SDR. It parses the payload to get the SDR ID, retrieves the sensitivity
 * config from the array, and sends it in the response.
 *
 * @param[in] pld Pointer to payload data with SDR ID  
 * @return Result code indicating success or failure of operation
*/
int8_t sdr_app_tc_get_sdr_sens_cfg(uint8_t *pld)
{
    uint8_t radio_id = 0;
    int8_t ret =0;

    os_memcpy(&radio_id,pld,sizeof(uint8_t));
    DEBUG_CPRINT(("Radio ID:%d ",radio_id));
    ret = SDR_GET_SENS_SUCCESS;

    sdr_app_tc_tm_get_rsp_hdlr(TM_GET_SDR_SENS_CFG, ret, sizeof(sdr_sens_cfg),(uint8_t *)&sdr_sens_cfg[radio_id]);

    return ret;
}

/**
 * @brief This function check the sband ground contact
 * 
 * @brief Check if ground station contact is valid
 *
 * This function checks if the ground station contact associated with
 * the given radio ID is valid and active.
 *
 * @param[in] radio_id The radio ID to check contact for
 * @return 1 if contact is valid, 0 if not valid
 * 
 */
uint8_t sdr_gs_contact_valid(uint8_t radio_id)
{
	uint8_t gs_contact_sts = 0;

	switch(radio_id)
	{
		case COMMS_S_BAND:
		{
			gs_contact_sts = is_sband_gs_contact_valid();
		}
		break;
		case COMMS_SBAND_IQS:
		{
			gs_contact_sts = is_sband_gs_contact_valid();
		}
		break;
		case COMMS_UHF:
		{
			gs_contact_sts = is_uhf_gs_contact_valid();
		}
		break;
	}
	return gs_contact_sts;
}


