/*
 * file_transfer.c
 *
 *  Created on: 30-Sep-2022
 *      Author: Invcuser52
 */

#include "file_transfer.h"

#include "ft_receiver.h"
#include "ft_sender.h"
#include "ft_timer.h"
#include "notify_apps.h"
#include "suspend_resume.h"


#include "ftsr.h"
#include "ftfci.h"
#include "ftci.h"
#include "ftds.h"

#include "ftsr_decode.h"
#include "ftfci_decode.h"
#include "ftci_decode.h"
#include "ftds_decode.h"


/* timeout time if sband link failure happens during FTM */
#define SBAND_FAILURE_SCT_ENABLE_TIMEOUT  500 // in ms
#define AUTO_SCT_ENABLE_WAIT_TIME (SBAND_FAILURE_SCT_ENABLE_TIMEOUT * 1000)

#ifdef FT_SUSRES_TEST
extern ftm_db_params ftm_db_test;
#endif

ft_compl_and_error_status ft_err_and_percent_info;

ft_payload_tx_type ft_payload_send;

ft_payload_obc_type ft_payload_obc_send;

ft_payload_obc_busycheck_type ft_payload_obc_busy_sts;

e_ft_current_process ft_process = ft_process_na;
tc_tm_id_e_ft ft_tc_request = FT_TC_TM_MAX_ID;
tc_tm_id_e_ft ft_tm_request = FT_TC_TM_MAX_ID;

uint16_t ftds_interval_delay = 200;
uint16_t manual_sband_fail_create_cnt=0;
uint8_t ftds_ack_en=0;
uint8_t rct_request_node_id;
void init_file_transfer()
{
//	ft_init_notify();
	init_sus_res();
	ft_init_timer();
	init_ftci();
	ft_payload_send = NULL;
	ft_payload_obc_send = NULL;
    ft_tx_session_id_update(FT_SESSION_ID_CLR);
}



void ft_send_tctm(uint16 tc_id, uint8 *tc_data, uint16 tc_data_len)
{
	uint16_t src_dst_id;
	if(tc_data != NULL)
	{

		if(tc_id == FT_TM_FTSR || tc_id == FT_TC_FTSR || tc_id == FT_TC_FTDR || tc_id == FT_TM_FTDR)
		{
			src_dst_id = ft_get_app_id_rx();
		}
		else
		{
			src_dst_id = ft_read_app_id_tx();
		}

		printf("FTM_TX:0%x\n",tc_id);

		ft_payload_send(tc_id, src_dst_id, tc_data, tc_data_len);

	}
	else
	{
		printf("FTM - GS/PS receive Null error\n");
	}
}



void ft_set_ftds_delay(uint16_t set)
{
	ftds_interval_delay = set;
	printf("FTDS delay set : %d\n",ftds_interval_delay);
}


uint8_t ft_get_ftds_delay(void)
{
	return ftds_interval_delay;
}

uint8_t sband_get_link_sts(void)
{
	uint8_t comm_sts;

	if(manual_sband_fail_create_cnt < 200)
	{
	//	u16cnt++;
		comm_sts = 1;
	}
	else
	{
		manual_sband_fail_create_cnt = 0;
		comm_sts = 0;
	}
	return comm_sts;
}


void sband_create_failure(void)
{
	manual_sband_fail_create_cnt = 500;
	printf("Sband fail trigger\n");

}


/*
 * Get the sband communication status
 * This will get get the status during FTM transmission, if comm is broken FTM will perform auto save context
 */
uint8_t ft_get_sband_link_status(void)
{
	static uint32_t u32cnt_timeout=0;
	uint8_t comm_sts;

	comm_sts = sband_get_link_sts();
	if(comm_sts != 1)
	{
		u32cnt_timeout++;
      	if(tx_info.seq_loss_detect_enable != SEQ_LOSS_DETECTION_OFF)
		{
			printf("[FTM - SBAND link fail] Auto savecontext activated.\n");
			ft_set_master_slave(sus_res_master);
			ft_suspend(Suspend_Savecontext_Auto_rqst,20,0);
			prepare_sts_and_notify_sender_app(transfer_suspended_auto_savecontext);

		}
      	else
      	{
			printf("Terminate FTM since FTM configured with Seq Loss & Recover option disabled\n");
			ft_transfer_request(T_Txnode,0);
      	}
	}
	else
	{
		u32cnt_timeout = 0;
	}
	return 1;
}


void* ft_handler(void* params)
{

	/*
	 *
	 */

	init_file_transfer();
	set_file_transfer_state(ft_process_na);
	//app1234_file_transfer_initiate();
	//ft_fsm_change_state(FT_Inactive);
	while(1)
	{
        usleep(1000);
    	ft_update_timer();
        ft_debug_handle();


		if(ft_process == ft_download)
		{
			ft_statemachine_download();  //fsm downloader
		}
		else if(ft_process == ft_upload)
		{
			ft_statemachine_upload();   //fsm uploader
		}
		else
		{
			// do nothing
		}
	}
}


e_ft_current_process get_file_transfer_state(void)
{
	return ft_process;
}

void set_file_transfer_state(e_ft_current_process set)
{
	 ft_process = set;
}

uint8_t ft_register_pld_trasnmitter_cblk(ft_payload_tx_type fp)
{
	uint8_t ret_sts = 0;
	if(fp != NULL)
	{
		ft_payload_send = fp;
		ret_sts = 1;
	}
	return ret_sts;
}






void ft_payload_parser(uint16 tc_tm_id, uint8_t src_dst_id, uint8_t *payload_ptr, uint16_t payload_len)
{

		if(payload_ptr != NULL)
		{
			if(ft_payload_send != NULL)
			{
				printf("FTM_RX:0%x\n",tc_tm_id);

				switch(tc_tm_id)
				{
				case FT_TC_FTCI:
				case FT_TM_FTCI:
				    ft_set_app_id_rx(src_dst_id);
					ft_receive_ftci(payload_ptr,payload_len);
					break;

				case FT_TC_FTFCI:
				case FT_TM_FTFCI:
				    ft_set_app_id_rx(src_dst_id);
					ft_receive_ftfci(payload_ptr,payload_len);
					break;

				case FT_TC_FTDS:
				case FT_TM_FTDS:
				    ft_set_app_id_rx(src_dst_id);
					ft_receive_ftds(payload_ptr,payload_len);
					break;

				case FT_TC_FTSR:
				case FT_TM_FTSR:
						rct_request_node_id = src_dst_id;
						ft_receive_ftsr(payload_ptr,payload_len);
					break;

				case FT_TC_FTDB:
				case FT_TM_FTDB:
					ft_decode_debug_request_frame(payload_ptr,payload_len);
					break;

				case FT_TC_FTDR:
				case FT_TM_FTDR:
					ft_decode_debug_response_frame(payload_ptr,payload_len);
					break;

				default :
					printf("Invalid input Parser\n");
					break;
				}
			}
			else
			{
				printf("Error !!! FTM messages are not processed due to ICD/TCTM sender callback not registered yet\n");
				printf("   Enable FTM Receiver for PS\n");
				/* can not send response since payload callback is not registered */
			}

		}
		else
		{
			printf("FT receive Null error\n");
		}
}




uint8_t ft_register_obc_trasnmitter_cblk(ft_payload_obc_type fp)
{
	uint8_t ret_sts = 0;
	if(fp != NULL)
	{
		printf("OBC sender callback registered\n");
		ft_payload_obc_send = fp;
		ret_sts = 1;
	}
	return ret_sts;
}



uint8_t ft_register_obc_flashbusy_sts_cblk(ft_payload_obc_busycheck_type fp)
{
	uint8_t ret_sts = 0;
	if(fp != NULL)
	{
		printf("OBC flash busy check callback registered\n");
		ft_payload_obc_busy_sts = fp;
		ret_sts = 1;
	}
	return ret_sts;
}



void ft_free_message_buffer(uint16 tc_tm_id)
{

		switch(tc_tm_id)
		{
		case FT_TC_FTCI:
		case FT_TM_FTCI:
			if(ftci_frame_info.str_ptr != NULL)
			{
				//free(ftci_frame_info.str_ptr);
			}
			break;

		case FT_TC_FTFCI:
		case FT_TM_FTFCI:
			if(ftfci_tctm_data.str_ptr != NULL)
			{
				free(ftfci_tctm_data.str_ptr);
			}
			break;

		case FT_TC_FTDS:
		case FT_TM_FTDS:
			if(seg_info.ftds_buf_ptr != NULL)
			{
				free(seg_info.ftds_buf_ptr);
			}
			break;

		case FT_TC_FTSR:
		case FT_TM_FTSR:
			if(ftsr_data_loss.str_ptr != NULL)
			{
				free(ftsr_data_loss.str_ptr);
			}
			break;

		default :
			break;

	}
}


e_ft_error_sts ft_get_error_sts(void)
{
	return ft_err_and_percent_info.error;
}

uint8_t ft_get_upload_percentage_compl(void)
{
	return ft_err_and_percent_info.upload_percentile;
}

void ft_set_err_sts(e_ft_error_sts err)
{
	ft_err_and_percent_info.error = err;
}

void ft_set_percentile_sts(uint8_t percent)
{
	ft_err_and_percent_info.upload_percentile = percent;
}

#ifndef FT_SAT
void ft_save_tc_request(tc_tm_id_e_ft set)
{
	ft_tc_request = set;
}


tc_tm_id_e_ft ft_get_tc_request(void)
{
	return ft_tc_request;
}
#else

void ft_save_tm_request(tc_tm_id_e_ft set)
{
	ft_tm_request = set;
}


tc_tm_id_e_ft ft_get_tm_request(void)
{
	return ft_tm_request;
}
#endif




void ft_sus_res_debug_enable(void)
{
#ifdef FT_SUSRES_TEST
	ft_sus_res_debug_init();
#endif
}

void ft_sus_res_debug_disable(void)
{
#ifdef FT_SUSRES_TEST
	ft_sus_res_debug_deinit();
#endif
}



void ft_sus_res_debug_skip_all_sus_req(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_sus_req_ = 1;
#endif
}

void ft_sus_res_debug_enable_all_sus_req(void)
{
#ifdef FT_SUSRES_TEST

	ftm_db_test.skip_all_sus_req_ = 0;
#endif
}

void ft_sus_res_debug_skip_all_sus_ack(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_sus_ack_ = 1;
#endif
}

void ft_sus_res_debug_enable_all_sus_ack(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_sus_ack_ = 0;
#endif
}

void ft_sus_res_debug_skip_all_res_req(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_res_req_ = 1;
#endif
}

void ft_sus_res_debug_enable_all_res_req(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_res_req_ = 0;
#endif
}

void ft_sus_res_debug_skip_all_res_ack(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_res_ack_ = 1;
#endif

}

void ft_sus_res_debug_enable_all_res_ack(void)
{
#ifdef FT_SUSRES_TEST
	ftm_db_test.skip_all_res_ack_ = 0;
#endif
}

