/**
 * @file api_req_orig.c
 *
 * @brief This file contains functions that helps to create
 *        the telecommand frame
 *
 * The functions provided in the file helps to create tele command
 * frame with crc and encryptions.
 *
 * @copyright Copyright 2023 Antaris, Inc.
 */
/*********************************************************************/
#include <api_req_common.h>
#include <crc_8.h>

/**
 * @brief This API initializes the s_api_req_frame by setting all the values
 *         of it's members to zero.
 */
int8_t api_req_orig_init(s_api_req_frame *api_req_orig)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        memset(api_req_orig, 0, sizeof(s_api_req_frame));
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the start of frame passed in sof value
 * to the sof member of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_sof(s_api_req_frame *api_req_orig, uint8_t sof1,
                                                          uint8_t sof2)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->sof1 = sof1;
        api_req_orig->sof2 = sof2;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the api_req_ctrl value to the api_req_ctrl member
 */
int8_t api_req_orig_cfg_api_req_ctrl(s_api_req_frame *api_req_orig,
        uint8_t api_req_ctrl)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->api_req_ctrl = api_req_ctrl;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the passed in api_req_id value to the api_req_id
 *  member of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_api_req_id(s_api_req_frame *api_req_orig,
        uint8_t api_req_id)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->api_req_id = api_req_id;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the passed in api_req_len value to the api_req_len
 *  member of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_api_req_len(s_api_req_frame *api_req_orig,
        uint16_t api_req_len)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->api_req_len = api_req_len;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the passed in value to the api_req_len member
 * of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_api_req_data(s_api_req_frame *api_req_orig,
        uint8_t *data)
{
    int8_t status;

    if((NULL != api_req_orig) && (NULL != data))
    {
        api_req_orig->api_req_data = data;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the passed in crc_8 value to the crc_8 member
 * of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_crc_8(s_api_req_frame *api_req_orig, uint8_t crc_8)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->crc_8 = crc_8;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @brief This API stores the passed in end of frame (eof) to the eof member
 * member of passed in s_api_req_frame type struct.
 */
int8_t api_req_orig_cfg_eof(s_api_req_frame *api_req_orig, uint8_t eof)
{
    int8_t status;

    if(NULL != api_req_orig)
    {
        api_req_orig->eof = eof;
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}


/**
 * @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.
 */
int8_t api_req_orig_compute_crc(const uint8_t *input_str, uint8_t *val,
        size_t size)
{

    int8_t status;

    if((NULL != input_str) && (NULL != val))
    {
        *val = CRC8(input_str, size);
        status = API_REQ_RESP_LIB_OK;
    }
    else
    {
        status = API_REQ_RESP_LIB_NULL_PTR;
    }

    return status;
}

/**
 * @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.
 */
int32_t api_req_pack(uint8_t *dst, s_api_req_frame *api_req_orig)
{
    int32_t size = 0;

    if((NULL != dst) && (NULL != api_req_orig))
    {
        memcpy(&dst[size], &api_req_orig->sof1, sizeof(api_req_orig->sof1));
        size += sizeof(api_req_orig->sof1);

        memcpy(&dst[size], &api_req_orig->sof2, sizeof(api_req_orig->sof2));
        size += sizeof(api_req_orig->sof2);

        memcpy(&dst[size], &api_req_orig->api_req_ctrl,
                sizeof(api_req_orig->api_req_ctrl));
        size += sizeof(api_req_orig->api_req_ctrl);
        if(api_req_orig->api_req_ctrl & API_REQ_RESP_SYNC_BIT)
        {
            api_req_orig->time_stamp = adcs_get_utc_epoch();

            memcpy(&dst[size], &api_req_orig->time_stamp,
                    sizeof(api_req_orig->time_stamp));

            size += sizeof(api_req_orig->time_stamp);
        }

        memcpy(&dst[size],&api_req_orig->api_req_id,
                sizeof(api_req_orig->api_req_id));
        size += sizeof(api_req_orig->api_req_id);

        memcpy(&dst[size],&api_req_orig->api_req_len,
                sizeof(api_req_orig->api_req_len));
        size += sizeof(api_req_orig->api_req_len);


        memcpy(&dst[size],api_req_orig->api_req_data,
                api_req_orig->api_req_len);
        size += api_req_orig->api_req_len;
        api_req_orig_compute_crc(dst, &api_req_orig->crc_8, size);

        memcpy(&dst[size], &api_req_orig->crc_8,
                sizeof(api_req_orig->crc_8));
        size += sizeof(api_req_orig->crc_8);
        memcpy(&dst[size], &api_req_orig->eof, sizeof(api_req_orig->eof));
        size += sizeof(api_req_orig->eof);
    }
    else
    {
        size = API_REQ_RESP_LIB_NULL_PTR;
    }

    return size;
}
