/**
 * @file tc_route_fwd.c
 *
 * @brief This file contains functions that helps to route
 *        the telecommand frame or data
 *
 * The functions provided in the file helps to route complete tele command
 * frame or just the data based on the user mentioned routing parameters.
 * The routing parameters are stored in the local data structure.
 *
 * @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 "tc_common.h"

/**
 * @brief This API searches for the routing table from the tc_fwd_head
 *        based on the da_id. If a routing table is found, it copies the
 *        routing information to the route_param of size equal to "size"
 *
 * @param[in] tc_fwd_head   : head node.
 * @param[in] da_id   : Destination Application id.
 * @param[out] route_param  : Pointer to the routing parameters
 * @param[in] size  : size of the routing table
 *
 * @return Result of API execution status
 * @retval TC_TM_LIB_OK -> Success / TC_TM_LIB_SEARCH_ERROR if No routing
 * parameter found forthe da_id or TC_TM_LIB_NULL_PTR -> Error.
 */
static int8 tc_get_rout_table(node *tc_fwd_head, uint16 da_id,
                              void *route_param, size_t size);

/**
 * @brief This API stores the route_param with it's da_id by inserting
 *  the new node to the end of the linear linked list. If the head
 *  node is not nulland the new node is null, the route_param will
 *  be stored with the head node
 */
int8 tc_add_rout_table(node *tc_fwd_head, node *new_node, uint16 da_id,
                       void *route_param)
{
    int8 status = TC_TM_LIB_SEARCH_ERROR;
    ;
    node *tmp = NULL;

    if((NULL == route_param) || (NULL == tc_fwd_head))
    {
        status = TC_TM_LIB_NULL_PTR;
    }
    else if(NULL == new_node)
    {
        // This call is made to populate head node
        tc_fwd_head->da_id = da_id;
        tc_fwd_head->route_param = route_param;
        tc_fwd_head->nxt = NULL;
        status = TC_TM_LIB_OK;
    }
    else
    {
        // This call is made to populate new node
        tmp = tc_fwd_head;
        while(NULL != tmp)
        {
            if(NULL == tmp->nxt)
            {
                tmp->nxt = new_node;
                new_node->da_id = da_id;
                new_node->route_param = route_param;
                new_node->nxt = NULL;
                status = TC_TM_LIB_OK;
                break;
            }
            tmp = tmp->nxt;
        }
    }

    return status;
}

/**
 * @brief This API searches for the routing table from the tc_fwd_head
 *        based on the da_id. If a routing table is found, it copies the
 *        routing information to the route_param of size equal to "size"
 */
static int8 tc_get_rout_table(node *tc_fwd_head, uint16 da_id,
                              void *route_param, size_t size)
{
    int8 status = TC_TM_LIB_SEARCH_ERROR;
    node *tmp_node = NULL;

    if(NULL == tc_fwd_head || NULL == route_param)
    {
        status = TC_TM_LIB_NULL_PTR;
    }
    else
    {
        tmp_node = tc_fwd_head;
        while(tmp_node != NULL)
        {
            if(tmp_node->da_id == da_id)
            {
                os_memcpy(route_param, tmp_node->route_param, size);
                status = TC_TM_LIB_OK;
                break;
            }
            else
            {
                tmp_node = tmp_node->nxt;
            }
        }
    }

    return status;
}

/**
 * @brief This API copies the routing parameters to the route_param
 *        based on the tc_orig->da_id. tc_fwd_add_rout_table ()
 *        need to invoked first to configure the routing table with da_id.
 */
int8 tc_route_pkt_hdrs(s_tc_frame *tc_orig, node *tc_fwd_head,
                       void *route_param, size_t size)
{
    int8 status;
    if((NULL != tc_orig) && (NULL != tc_fwd_head))
    {
        status =
            tc_get_rout_table(tc_fwd_head, tc_orig->da_id, route_param, size);
    }
    else
    {
        status = TC_TM_LIB_NULL_PTR;
    }
    return status;
}

/**
 * @brief This API copies the routing parameters to the route_param
 *        based on the tc_orig->da_id and tc_orig->data to the data param
 *        of size tc_orig->tc_len. tc_fwd_add_rout_table () need to be
 *        invoked first to configure the routing table with da_id.
 */
int8 tc_route_pkt(s_tc_frame *tc_orig, node *tc_fwd_head, void *route_param,
                  size_t size, uint8 *data)
{
    int8 status;
    if((NULL != tc_orig) && (NULL != data) && (NULL != tc_fwd_head))
    {
        status =
            tc_get_rout_table(tc_fwd_head, tc_orig->da_id, route_param, size);
        os_memcpy(data, tc_orig->tc_data, tc_orig->tc_len);
    }
    else
    {
        status = TC_TM_LIB_NULL_PTR;
    }
    return status;
}
