/**
 * @file ft_debug.c
 *
 * @brief This file contains functions that provides demonstration of
 *        usage of debug message encoding
 *
 * The functions provided in the file provides demonstration on
 * usage of debug message encoding
 *
 * @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.
 *
 */


/*
 *
 *  Get FTM status  >> e_ft_debug_status
1	FT process = upload / download   = get_file_transfer_state(); 2 bit
2	FT fsm    = ft_fsm_read_state()             2 bit
3	Node type = master/ receiver
4	Sus / Resume status    = ft_get_suspend_resume_sts();   2 bit
5	Sequence loss status  = ft_get_seq_loss_status();    2 bit
6   Head position =  ft_get_receiver_head_seq_id();     32 bit
 *
 *
 */


/******************************************************************************/
/*                            Include other headers                           */
/******************************************************************************/


#include "ft_debug.h"
#include "file_transfer.h"
#include "ftds_decode.h"
#include "suspend_resume.h"
#include "tc_tm_sample.h"
#include "logger.h"


/******************************************************************************/
/*                       Definition of local variables                        */
/******************************************************************************/


static ft_debug_sel 		ft_ftdb = e_ft_none;
static ft_debug_gen_sts 	ft_db_gen_sts;
static s_string_info 		ftdb_frame;


/******************************************************************************/
/*                  Declaration of local function prototypes                  */
/******************************************************************************/

/**
 * @brief This function encode the debug response frame
 *
 * @param[in] response_code : type of debug message
 * @param[in] data : pointer to buffer contains debug read data
 * @param[in] ftdb_data_length : length of frame
 *
 * @return none
 */
static void prepare_ftdp_response_frame(uint8_t response_code, uint8_t *data, uint8_t data_len);



/******************************************************************************/
/*                       Definition of local functions                        */
/******************************************************************************/


/**
 * @brief This function encode the debug response frame
 */
static void prepare_ftdp_response_frame(uint8_t response_code, uint8_t *data, uint8_t data_len)
{
	s_string_info ftdp_tctm_data;
	ftdp_tctm_data.str_ptr = os_malloc(data_len+1);
	if(ftdp_tctm_data.str_ptr != NULL)
	{
		*ftdp_tctm_data.str_ptr = response_code;
		if(data_len != 0)
		{
			memcpy(ftdp_tctm_data.str_ptr+1, data, data_len);
		}
		ftdp_tctm_data.size = data_len+1;

#ifndef FT_SAT
		ft_send_tm_to_obc(FT_TC_FTDR, ftdp_tctm_data.str_ptr, ftdp_tctm_data.size);
#else
		ft_send_tm_to_obc(FT_TM_FTDR, ftdp_tctm_data.str_ptr, ftdp_tctm_data.size);
#endif
		os_free(ftdp_tctm_data.str_ptr);
	}
	else
	{
		DEBUG_CPRINT(("FTM: malloc error\n"));
	}

}


/******************************************************************************/
/*                      Definition of exported functions                      */
/******************************************************************************/


/**
 * @brief This function decode the debug request type and prepare response
 *
 * Receive debug message
 */
void ft_decode_debug_request_frame(uint8_t *ftdb_data, uint16_t ftdb_data_length)
{
	ftdb_frame.str_ptr = os_malloc(ftdb_data_length);
	if(ftdb_frame.str_ptr != NULL)
	{
		if(*ftdb_data < e_ft_debug_max)
		{
			ft_ftdb = (ft_debug_sel)*ftdb_data;
			DEBUG_CPRINT(("FTDB Request received.\n"));
			log_id(LOG_INFO_L1, LOG_FTM, FTDB_REQUEST_RECEIVED);
			memcpy(ftdb_frame.str_ptr, ftdb_data, ftdb_data_length);
			if(ft_get_service_activity_status() != 1)
			{
				ft_debug_handle();
			}
		}
		else
		{
			DEBUG_CPRINT(("FTDB input invalid\n"));
			os_free(ftdb_frame.str_ptr);
		}
	}
	else
	{
		DEBUG_CPRINT(("FTM malloc fail\n"));
	}

}


/**
 * @brief This function decode the debug response frame
 *
 * Receive debug message
 */
void ft_decode_debug_response_frame(uint8_t *ftdr_data, uint16_t ftdr_data_length)
{

	ft_debug_gen_sts *ft_db_gen_sts_ptr;
//	uint8_t u8ctr;
	CPRINT_VARIABLE_UNUSED(ft_db_gen_sts_ptr);
	if(*ftdr_data <= e_ft_reset)
	{
/*		DEBUG_CPRINT(("FTDR Response received of size:%d.\n",ftdr_data_length));

		for(u8ctr =0; u8ctr < ftdr_data_length; u8ctr++)
		{
			DEBUG_CPRINT(("%d,",ftdr_data[u8ctr]));
		}*/
		DEBUG_CPRINT(("\n"));

		switch(*ftdr_data)
		{
			case e_ft_none:
				break;

			case e_ft_debug_gen_status:
				ft_db_gen_sts_ptr = (ft_debug_gen_sts*)&ftdr_data[1];
				DEBUG_CPRINT(("FT_Debug - Get gen status\n"));
				DEBUG_CPRINT(("FSM: %d\n",ft_db_gen_sts_ptr->fsm_st));
				DEBUG_CPRINT(("Operation: %d\n",ft_db_gen_sts_ptr->ft_proc_st));
				DEBUG_CPRINT(("Suspend: %d\n",ft_db_gen_sts_ptr->sus_res_st));
				DEBUG_CPRINT(("Seq loss status: %d\n",ft_db_gen_sts_ptr->seq_loss_st));
				DEBUG_CPRINT(("FTM Service run status: %d\n",ft_db_gen_sts_ptr->service_run_sts));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
				DEBUG_CPRINT(("Head position: %lu\n",ft_db_gen_sts_ptr->head_pos));
                if(ft_db_gen_sts_ptr->prev_tctm_id == 100)
                {
                        DEBUG_CPRINT(("Previous TCTM ID: FTCI\n"));
                }
                else if(ft_db_gen_sts_ptr->prev_tctm_id == 102)
                {
                        DEBUG_CPRINT(("Previous TCTM ID: FTDS\n"));
                }
                else if(ft_db_gen_sts_ptr->prev_tctm_id == 103)
                {
                         DEBUG_CPRINT(("Previous TCTM ID: FTFCI\n"));
                }

				DEBUG_CPRINT(("Previous TCTM Response: %d\n",ft_db_gen_sts_ptr->prev_tctm_response));
#pragma GCC diagnostic pop
				break;

			case e_ft_debug_sct_status:
				DEBUG_CPRINT(("FT_Debug - SCT-OTSU\n"));
				break;

			case e_ft_debug_terminate:
				DEBUG_CPRINT(("FT_Debug - Terminate FTM\n"));
				log_id(LOG_ERROR, LOG_FTM, FT_DEBUG_TERMINAL_FTM);
				break;

			case e_ft_reset:
				DEBUG_CPRINT(("FT_Debug - FT Reset\n"));
				break;

			default :
				break;
		}

	}
	else
	{
		DEBUG_CPRINT(("FTDR input invalid\n"));
	}
}





/**
 * @brief This function prepares response frame for debug request
 *
 */
void ft_debug_handle(void)
{
	uint16_t tctm_id,response;
	if(ft_ftdb != e_ft_none)
	{
		switch(ft_ftdb)
		{
			case e_ft_none:
				break;

			case e_ft_debug_gen_status:
				DEBUG_CPRINT(("FT_Debug - Get gen status\n"));
				ft_db_gen_sts.head_pos = ft_get_receiver_head_seq_id();
				ft_db_gen_sts.fsm_st = ft_fsm_read_state();
				ft_db_gen_sts.ft_proc_st = get_file_transfer_state();
				ft_db_gen_sts.sus_res_st = ft_get_suspend_resume_sts();
				ft_db_gen_sts.seq_loss_st = ft_get_seq_loss_sts();
				ft_get_debug_last_tctm_and_response(&tctm_id, &response);
				ft_db_gen_sts.prev_tctm_id = tctm_id;
				ft_db_gen_sts.prev_tctm_response = response;
				ft_db_gen_sts.service_run_sts = ft_get_service_activity_status();
				prepare_ftdp_response_frame((uint8_t)e_ft_debug_gen_status, (uint8_t*)&ft_db_gen_sts, sizeof(ft_debug_gen_sts) );
				break;

			case e_ft_debug_sct_status:
				DEBUG_CPRINT(("FT_Debug - SCT-OTSU\n"));
				break;

			case e_ft_debug_terminate:
				DEBUG_CPRINT(("FT_Debug - Terminate FTM\n"));
				log_id(LOG_WARNING, LOG_FTM, FT_DEBUG_TERMINATE_FTM);
				ft_transfer_request(Terminate_Transmission_rqst,0);
				break;

			case e_ft_reset:
				DEBUG_CPRINT(("FT_Debug - FT Reset\n"));
				log_id(LOG_INFO_L1, LOG_FTM, FT_DEBUG_FT_RESET);
				ft_fsm_change_state(FT_Idle_State);
				set_file_transfer_state(ft_process_na);
				init_sus_res();
				ft_service_disable();
				prepare_ftdp_response_frame((uint8_t)e_ft_reset, NULL, 0);
				break;


			case e_ft_debug_integ_test:
				DEBUG_CPRINT(("FT_Debug - Skip suspend T mode\n"));
#if EN_INTG_TEST_CODE
				if(*ftdb_frame.str_ptr[1] == e_ft_test_ig_sus_rq)
				{
					ftm_db_test.ignore_sus_request = *ftdb_frame.str_ptr[2] & 0x1;
					DEBUG_CPRINT(("e_ft_test_ig_sus_rq - %d\n",ftm_db_test.ignore_sus_request));
				}
				else if(*ftdb_frame.str_ptr[1] == e_ft_test_ig_sus_ack)
				{
					ftm_db_test.dont_send_ack_for_sus_rqst = *ftdb_frame.str_ptr[2] & 0x1;
					DEBUG_CPRINT(("e_ft_test_ig_sus_ack - %d\n",ftm_db_test.dont_send_ack_for_sus_rqst));
				}
				else if(*ftdb_frame.str_ptr[1] == e_ft_test_ig_res_rq)
				{
					ftm_db_test.ignore_res_request = *ftdb_frame.str_ptr[2] & 0x1;
					DEBUG_CPRINT(("e_ft_test_ig_res_rq - %d\n",ftm_db_test.ignore_res_request));
				}
				else if(*ftdb_frame.str_ptr[1] == e_ft_test_ig_res_ack)
				{
					ftm_db_test.dont_send_ack_for_res_rqst = *ftdb_frame.str_ptr[2] & 0x1;
					DEBUG_CPRINT(("e_ft_test_ig_res_ack - %d\n",ftm_db_test.dont_send_ack_for_res_rqst));
				}
				else
				{
					DEBUG_CPRINT(("e_ft_test invalid\n"));
				}
#endif
				break;

			default :
				break;
		}

		/* clear request */
		ft_ftdb = e_ft_none;
		os_free(ftdb_frame.str_ptr);
	}
}
/*
 * This function is used to save the previous frame information
 */
void ft_debug_save_prev_frame_info(uint16_t tctm_id , uint16_t response)
{
	ft_db_gen_sts.prev_tctm_id = tctm_id;
	ft_db_gen_sts.prev_tctm_response = response;
}
/*
 * This function is used to get the previous frame information
 */
void ft_get_debug_last_tctm_and_response(uint16_t* tctm_id , uint16_t* response)
{
	*tctm_id  = ft_db_gen_sts.prev_tctm_id;
	*response = ft_db_gen_sts.prev_tctm_response;
}

