/**
 * @file api_resp_common.h
 *
 * @brief This file contains function prototypes and data definitions that
 * helps to create and unpack a TC frame
 *
 * @copyright Copyright 2023 Antaris, Inc.
 */

#ifndef API_RESP_COMMAN_H_
#define API_RESP_COMMAN_H_

#include "api_req_resp_lib_common.h"

#ifdef __cplusplus
extern "C" {
#endif
/**@}*/
/**\name C standard macros */
#ifndef NULL
#ifdef __cplusplus
#define NULL                            (0)  ///< value for NULL 
#else
#define NULL                            ((void *) 0) ///< NULL in void pointer
#endif
#endif

/// Limits definitions
#define API_RESP_ID_MAX            (1024)    ///< TC id maximum limit
#define API_RESP_MIN_LEN           (8)      ///< Minimum TC length

/// encrypt/decrypt and authentication related definitions
#define TC_CTRL_CRYPT_BIT    (0x20)   ///< encrypt/decrypt bit
#define TC_CTRL_CRYPT_POS    (0x5)    ///< encrypt/decrypt bit position
#define TC_CTRL_AUTH_BIT     (0x10)   ///< encrypt/decrypt bit
#define TC_CTRL_AUTH_POS     (0x4)    ///< encrypt/decrypt bit position

/*************************** Data structures *******************************/
/**
 * @brief Api-Request frame structure definition
 *
 */
typedef struct api_tc_frame
{
    uint8_t   sof1;                  /*!< Start of Frame indicator1 */
    uint8_t   sof2;                  /*!< Start of Frame indicator2 */
    uint8_t   api_resp_ctrl;         /*!< Api-Request control */
    uint32_t  time_stamp;            /*!< Time stamp value */
    uint16_t  seq_no;                /*!< Sequence number */
    uint8_t  api_resp_id;            /*!< Api-Request id */
    uint16_t  api_resp_len;          /*!< Api-Request data length */
    uint8_t*  api_resp_data;         /*!< Api-Request data */
    uint8_t   crc_8;                 /*!< CRC value */
    uint8_t   eof;                   /*!< End of Frame indicator */
}s_api_resp_frame;

/**
 * @brief function pointer to trigger function
 */

typedef   int (*api_resp_trgr_ptr)(s_api_resp_frame *);


/**
 * @brief Control field info structure for telecommand
 */
typedef struct api_tc_ctrl
{
    uint8_t source_dest : 1;    /*!< Source Destination identifier */
    uint8_t sync        : 1;    /*!< Synchronous or Asynchronous mode */
    uint8_t reserved    : 6;    /*!< Reserved */
}s_api_resp_ctrl;

/**
 * @brief Utility data type to populate s_tc_ctrl structure
 */
typedef union
{
    s_api_resp_ctrl ctrl;      /*!< s_tc_ctrl structure instance */
    uint8_t byte;              /*!< 8 bit utility variable  */
}s_api_resp_ctrl_util;

/**
 * @brief This API initializes the s_tc_frame by setting all the values of
 *         it's memebers to zero.
 *
 * @param[in] api_resp_orig     : Structure instance of s_tc_frame.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR
 *         -> Error.
 */
int8_t api_resp_orig_init(s_api_resp_frame *api_resp_orig);

/**
 * @brief This API stores the start of frame passed in sof value to
 * to the sof members of passed in s_api_resp_frame type struct.
 *
 * @param[in] api_resp_orig     : Structure instance of s_tc_frame.
 * @param[in] sof1         : Start Of frame value 1.
 * @param[in] sof2         : Start Of frae value 2.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR
 *         -> Error.
 */
int8_t api_resp_orig_cfg_sof(s_api_resp_frame *api_resp_orig,uint8_t sof1,
                                                     uint8_t sof2);

/**
 * @brief This API stores the passed in tc_ctrl value to the tc_ctrl member of
 *         the passed in s_tc_frame type struct
 *
 * @param[in] api_resp_orig     : Structure instance of s_tc_frame.
 * @param[in] tc_ctrl     : tc_ctrl value.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR
 *         -> Error.
 */
int8_t api_resp_orig_cfg_api_resp_ctrl(s_api_resp_frame *api_resp_orig,
        uint8_t tc_ctrl);

/**
 * @brief This API stores the passed in tc_id value to the tc_id member of
 *         the passed in s_tc_frame type struct
 *
 * @param[in] api_resp_orig    : Structure instance of s_tc_frame.
 * @param[in] api_resp_id      : Tele Command Id.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR
 *         -> Error.
 */
int8_t api_resp_orig_cfg_api_resp_id(s_api_resp_frame* api_resp_orig,
        uint8_t api_resp_id);

/**
 * @brief This API stores the passed in tc_len value to the tc_len member of
 *         the passed in s_tc_frame type struct
 *
 * @param[in] api_resp_orig    : Structure instance of s_tc_frame.
 * @param[in] tc_len      : Tele Command data Length.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR
 *         -> Error.
 */
int8_t api_resp_orig_cfg_api_resp_len(s_api_resp_frame* api_resp_orig,
        uint16_t tc_len);
/**
 * @brief This API stores the passed in value to the api_resp_len member
 * of passed in s_api_resp_frame type struct.
 *
 * @param[in] api_req_orig : pointer Structure instance of s_api_req_frame.
 * @param[in] data : pointer to request data.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_orig_cfg_api_resp_data(s_api_resp_frame *api_resp_orig,
        uint8_t *data);

/**
 * @brief This API stores the passed in crc_8 value to the crc_8 member of
 *         the passed in s_tc_frame type struct
 *
 * @param[in] api_resp_orig    : Structure instance of s_tc_frame.
 * @param[in] crc_8      : crc8 value.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_orig_cfg_crc_8(s_api_resp_frame* api_resp_orig, uint8_t crc_8);

/**
 * @brief This API stores the passed in eof value to the eof member of the
 *        passed in s_tc_frame type struct
 *
 * @param[in] api_resp_orig     : Structure instance of s_tc_frame.
 * @param[in] eof         : End Of Frame (eof) value.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_orig_cfg_eof(s_api_resp_frame *api_resp_orig, uint8_t eof);

/**
 * @brief This API calculates the crc for the passed in input_str
 *         for the input size and stores the crc value to the val parameter
 *         equal to size input value.
 *
 * @param[in] input_str : Input buffer for which the crc needs to be
 *                         calculated
 * @param[out] val      : Pointer to the computed crc.
 * @param[in] size      : size of the input buffer
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_orig_compute_crc(const uint8_t *input_str, uint8_t* val,
        size_t size);

/**
 * @brief This API stores the start of frame sof from the sof member of passed
 * in s_api_resp_frame type struct to passed in sof and value.
 *
 * @param[in] api_resp_term    : Structure instance of s_tc_frame.
 * @param[out] sof1       : Pointer to sof1 data.
 * @param[out] sof2       : Pointer to sof2 data.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_term_extract_sof(s_api_resp_frame *api_resp_term,uint8_t *sof1,
                                                                uint8_t *sof2);

/**
 * @brief This API populates the members of tc_ctrl input structure based on
 *         the tc_term->tc_ctrl value.
 *
 * @param[in] api_resp_term    : Structure instance of s_tc_frame.
 * @param[out] api_resp_ctrl   : Structure instance of s_tc_ctrl.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_term_extract_api_resp_ctrl(s_api_resp_frame *api_resp_term,
        s_api_resp_ctrl *api_resp_ctrl);

/**
 * @brief This API stores the tele command id (tc_id) from the tc_id
 *        member of passed in s_tc_frame type struct to passed in tc_id
 *        pointer
 *
 * @param[in] api_resp_term    : Structure instance of s_tc_frame.
 * @param[out] api_resp_id       : Pointer to tc_id data.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_term_extract_api_resp_id(s_api_resp_frame *api_resp_term,
        uint8_t *api_resp_id);

/**
 * @brief This API stores the api request data length (api_resp_len) from the
 *         api_resp_len member of passed in s_api_resp_frame type struct to
 *         passed in tc_len pointer
 *
 * @param[in] api_resp_term    : Structure instance of s_api_resp_frame.
 * @param[out] api_resp_len       : Pointer to tc_len data.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_term_extract_api_resp_len(s_api_resp_frame *api_resp_term,
        uint16_t *api_resp_len);

/**
 * @brief This API stores the end of frame (eof) from the sof member of passed
 *        in s_api_resp_frame type struct to passed in eof pointer
 *
 * @param[in] api_resp_term    : Structure instance of s_tc_frame.
 * @param[out] eof       : Pointer to eof data.
 *
 * @return Result of API execution status
 * @retval API_REQ_RESP_LIB_OK -> Success / API_REQ_RESP_LIB_NULL_PTR ->
 *          Error.
 */
int8_t api_resp_term_extract_eof(s_api_resp_frame *api_resp_term,
        uint8_t *eof);

/**
 * @brief This API copies the structure data to the output buffer(dst). While
 * copying it takes care of the extension bit for the required members.
 * Finally it computes CRC and embeds those value to the final
 * output buffer(dst).
 *
 * @param[out] dst     : pointer to the output buffer
 * @param[in] api_resp_orig  : Structure instance of s_tc_frame.
 *
 * @return Size of the output buffer if all operations are 
 *         success else failure code
 * @retval 0 or greater than zero-> success less than zero ->failure
 */
int32_t api_resp_pack(uint8_t *dst, s_api_resp_frame *api_resp_orig);

/**
 * @brief This API copies the structure data to the input buffer(dst) to the
 *        input structure. It also computes crc for the input buffer
 *        and compares it with the embedded values.
 *
 * @param[in] dst     : pointer to the input buffer
 * @param[in] len     : input buffer len
 * @param[out] api_resp_orig  : Structure instance of s_tc_frame.
 *
 * @return Size of the unpacked data if the crc and hmac checks are success 
 *         else failure code
 * @retval 0 or greater than zero-> success less than zero ->failure
 */
int32_t api_resp_unpack(const uint8_t *dst, uint16_t len,
        s_api_resp_frame *api_resp_orig);

#ifdef __cplusplus
}
#endif
#endif /*API_RESP_COMMAN_H_*/
