/******************************************************************************/
/**
 * @file file_transfer.c
 *
 * @brief This file contains function that helps to handle app notification
 *
 * The functions provided in the file provides demonstration on
 * usage of file tranmission, resume transmission
 *
 * @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.
 *        usage of TC TM Library APIs
 */
/******************************************************************************/

/******************************************************************************/
/*                      Include headers of the component                      */
/******************************************************************************/

#include "suspend_resume.h"
#include "file_transfer.h"
#include "ftfci.h"
#include "ftci_decode.h"
#include "message_frame_def.h"
#include "ftsr.h"
#include "ftfci_decode.h"
#include "ftci_decode.h"
#include "stdio.h"
#include "notify_apps.h"
#include "ftsr_decode.h"
#include "ftds_decode.h"
#include "ft_debug.h"
#include "exo_common.h"

#ifdef FT_SUSRES_TEST
ftm_db_params ftm_db_test;
#endif

/******************************************************************************/
/*                  Definition of local function like macros                  */
/******************************************************************************/

/* FTDS receive check timeout time 5 seconds*/
#define FTDS_RX_CHECK_INTERVAL (5 * FT_TICK_TIME_IN_SEC)


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

static uint16_t 					sus_temp;
static uint8_t 						resume_accepted_slave = 0;
static uint8_t 						sus_res_dwld_side_rqst_raise = 0;
static uint8_t 						u8_ftds_rx_ctr=0;
static uint8_t 						ftds_incoming_flag;
static uint8_t 						sus_sct_avail;

/******************************************************************************/
/*                      Definition of exported variables                      */
/******************************************************************************/
s_suspend_resume_info 				s_sus_res_info;

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

/**
 * @brief This function used to prepare suspend request frame
 *
 *
 * @param[in]  susp_type : type of suspend request whether suspend-timeout or suspend-savecontext mode
 * @param[in]  timeoout_time : timeout value
 * @param[in]  ack_set : option to enable response frame *
 *
 * @return none
 * @retval void : none
 */
static void prepare_suspend_request_frame(ft_request susp_type, uint16_t timeoout_time, uint8_t ack_set);

/**
 * @brief This function used to prepare resume request frame
 *
 *
 * @param[in]  resume_type : type of suspend request whether suspend-timeout or suspend-savecontext mode
 * @param[in]  ack_set : option to enable response frame
 *
 *
 * @return none
 * @retval void : none
 */
static void prepare_resume_request_frame(uint8_t resume_type, uint8_t ack_set);





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



/**
 * @brief This function used to prepare suspend request frame
 *
 */
static void prepare_suspend_request_frame(ft_request susp_type, uint16_t timeoout_time, uint8_t ack_set)
{
	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();
	DEBUG_CPRINT(("SUS_Frame: susp_type=%d, timeoout_time=%d, ack_set=%d\n",susp_type,timeoout_time,ack_set));

	if(ft_state == ft_upload)
	{
		if(ack_set == 1)
		{
			send_ftfci(ftfci_ack,timeoout_time);
			if(susp_type == Suspend_Timeout_Mode_rqst)
			{
				s_sus_res_info.type = suspend_by_timeout;
			}
		}
		else if(ack_set == 2)
		{
			send_ftfci(ftfci_nak,timeoout_time);
		}
		else if(ack_set == 3)
		{
			DEBUG_CPRINT(("Skip ACK, since app will taken care to send ACK/NAK\n"));
			if(susp_type == Suspend_Savecontext_Mode_rqst)
			{
				s_sus_res_info.type = suspend_by_savecontext;
				sus_sct_avail = 1;
			}
		}
		else
		{
			if(susp_type == Suspend_Timeout_Mode_rqst)
			{
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_sus_request != 1 &&
				   ftm_db_test.skip_all_sus_req_ != 1)
#endif
				{
					send_ftfci(ftfci_suspend,timeoout_time);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for ST"));
					ftm_db_test.ignore_sus_request = 0;
					/* 1 = fail next trial ; 0 = pass next trial */
					ftm_db_test.dont_send_ack_for_sus_rqst = 1;
					ftm_db_test.dont_send_ack_for_res_rqst = 0;
				}
#endif
				s_sus_res_info.type = suspend_by_timeout;
			}
			else if(susp_type == Suspend_Savecontext_Mode_rqst)
			{
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_sus_request != 1 &&
					   ftm_db_test.skip_all_sus_req_ != 1)
#endif
				{
					send_ftfci(ftfci_suspend_savecontext,timeoout_time);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for SCT"));
					ftm_db_test.ignore_sus_request = 0;
					/* 1 = fail next trial ; 0 = pass next trial */
					ftm_db_test.dont_send_ack_for_sus_rqst = 1;
					ftm_db_test.dont_send_ack_for_res_rqst = 0;
				}
#endif
				s_sus_res_info.type = suspend_by_savecontext;
			}
			else
			{
				DEBUG_CPRINT(("[FTM] SkiP sus_ctxt_rqst to slave\n"));
				s_sus_res_info.type = suspend_by_savecontext;
			}
		}
	}
	else
	{
		if(ack_set == 1)
		{
			send_ftsr(ftsr_ack,timeoout_time);
			s_sus_res_info.type = suspend_by_timeout;
		}
		else if(ack_set == 2)
		{
			send_ftsr(ftsr_nak,timeoout_time);
		}
		else if(ack_set == 3)
		{
			DEBUG_CPRINT(("Skip ACK, since app will taken care to send ACK/NAK\n"));
			if(susp_type == Suspend_Savecontext_Mode_rqst)
			{
				s_sus_res_info.type = suspend_by_savecontext;
			}
		}
		else
		{
			if(susp_type == Suspend_Timeout_Mode_rqst)
			{
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_sus_request != 1 &&
					   ftm_db_test.skip_all_sus_req_ != 1)

#endif
				{
					send_ftsr(ftsr_suspend,timeoout_time);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for ST"));
					ftm_db_test.ignore_sus_request = 0;
					/* 1 = fail next trial ; 0 = pass next trial */
					ftm_db_test.dont_send_ack_for_sus_rqst = 1;
					ftm_db_test.dont_send_ack_for_res_rqst = 0;
				}
#endif
				s_sus_res_info.type = suspend_by_timeout;
			}
			else if(susp_type == Suspend_Savecontext_Mode_rqst)
			{
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_sus_request != 1 &&
					   ftm_db_test.skip_all_sus_req_ != 1)
#endif
				{
					send_ftsr(ftsr_suspend_savecontext,timeoout_time);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for SCT"));
					ftm_db_test.ignore_sus_request = 0;
					/* 1 = fail next trial ; 0 = pass next trial */
					ftm_db_test.dont_send_ack_for_sus_rqst = 1;
					ftm_db_test.dont_send_ack_for_res_rqst = 0;
				}
#endif
				s_sus_res_info.type = suspend_by_savecontext;
			}
		}
		sus_res_dwld_side_rqst_raise = 1;
	}
}


/**
 * @brief This function used to prepare resume request frame
 *
 *
 */
static void prepare_resume_request_frame(uint8_t resume_type, uint8_t ack_set)
{
	e_ft_current_process ft_state;

	DEBUG_CPRINT(("RES_Frame: resume_type=%d, ack_set=%d\n",resume_type,ack_set));

	ft_state =  get_file_transfer_state();
	if(ft_state == ft_upload)
	{
		if(ack_set == 1)
		{
			send_ftfci(ftfci_ack,0);
		}
		else
		{
			if(resume_type == Resume_Timeout_Mode_rqst)
			{
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_res_request != 1 &&
					   ftm_db_test.skip_all_res_req_ != 1)

#endif
				{
					send_ftfci(ftfci_resume,0);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for RT"));
					ftm_db_test.ignore_res_request = 0;
					/* 1 = allow next request ;  0 = dont allow */
					ftm_db_test.dont_send_ack_for_res_rqst = 1;

					ftm_db_test.dont_send_ack_for_sus_rqst = 0;
				}
#endif
				s_sus_res_info.type = suspend_by_timeout;
			}
			else
			{
				s_sus_res_info.type = suspend_by_savecontext;
			// commented during RCT by FTCI//	send_ftfci(ftfci_resume_savecontext,0);
			}
		}
	}
	else
	{
		if(ack_set == 1)
		{
			send_ftsr(ftsr_ack,0);
		}
		else
		{
			if(resume_type == Resume_Timeout_Mode_rqst)
			{
				s_sus_res_info.type = suspend_by_timeout;
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_res_request != 1 &&
					   ftm_db_test.skip_all_res_req_ != 1)

#endif
				{
				send_ftsr(ftsr_resume,0);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for RT"));
					ftm_db_test.ignore_res_request = 0;
					/* 1 = allow next request ;  0 = dont allow */
					ftm_db_test.dont_send_ack_for_res_rqst = 1;

					ftm_db_test.dont_send_ack_for_sus_rqst = 0;
				}
#endif
			}
			else
			{
				s_sus_res_info.type = suspend_by_savecontext;
#ifdef FT_SUSRES_TEST
				if(ftm_db_test.ignore_res_request != 1 &&
					   ftm_db_test.skip_all_res_req_ != 1)

#endif
				{
				send_ftsr(ftsr_resume_savecontext,0);
				}
#ifdef FT_SUSRES_TEST
				else
				{
					DEBUG_CPRINT(("[FT-DB-Test] Skip FTFCI for RCT\n"));
					ftm_db_test.ignore_res_request = 0;
					/* 1 = allow next request ;  0 = dont allow */
					ftm_db_test.dont_send_ack_for_res_rqst = 1;

					ftm_db_test.dont_send_ack_for_sus_rqst = 0;
				}
#endif
			}
		}
	}
	sus_res_dwld_side_rqst_raise = 0;
}



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



/**
 * @brief This function used to process the suspend request has come from other node
 *
 */
void ft_suspend(ft_request susp_type, uint16_t timeoout_time, uint8_t ack_set)
{
	e_sus_res_state sus_state;
	e_avtive_type node_act_type;

	sus_state =  ft_get_suspend_resume_sts();
	if(sus_state == no_suspend_reusume)
	{
		s_sus_res_info.fsm_state_save = ft_fsm_read_state();
		DEBUG_CPRINT(("Suspend - Saved FSM state %d \n",s_sus_res_info.fsm_state_save));
	}
	else
	{
		// do nothing since transmission already in suspend/resume state
	}

	s_sus_res_info.state = state_suspend;
	ft_fsm_change_state(FT_Suspended);
	ft_stop_timer();
	prepare_suspend_request_frame(susp_type, timeoout_time, ack_set);

	/* only works when node is slave to run the timeout timer*/
	node_act_type = ft_get_master_slave_status();
	if(node_act_type == sus_res_slave)
	{
		ft_set_timer(timeoout_time);
		s_sus_res_info.timeout_time_save = timeoout_time;
		s_sus_res_info.request_clear_flag = 1;
		s_sus_res_info.sus_res_state_copy = state_suspend;
		ft_set_timer(SUS_RES_RESPONSE_WAIT_SEC+2);
	}
	else
	{
		s_sus_res_info.request_clear_flag = 1;
		s_sus_res_info.sus_res_rqst_retry_count++;
		s_sus_res_info.sus_res_state_copy = state_suspend;
		ft_set_timer(SUS_RES_RESPONSE_WAIT_SEC);
	}

	sus_temp = timeoout_time;
	resume_accepted_slave = 0;
	u8_ftds_rx_ctr = 0;
}

/**
 * @brief This function used to process the resume request has come from other node
 *
 *
 */
void ft_resume(uint8_t resume_type, uint8_t ack_set )
{
	e_ft_current_process ft_state;
	e_avtive_type node_act_type;

	if(s_sus_res_info.state == state_suspend)
	{
		ft_state =  get_file_transfer_state();
		if(ft_state == ft_upload)
		{
			/* change state to resume state if node is acting as sender to avoid sudden start of sending the FTDS
			 * FTDS transmission will start in ft_sus_res_handler() after 10 cycles
			 *  */
			ft_fsm_change_state(FT_Resumed);
			s_sus_res_info.state = state_resume;
			s_sus_res_info.resume_time =0;
			ft_set_timer(SENDER_RESPONSE_WAIT_TIME);
		}
		else
		{
			node_act_type = ft_get_master_slave_status();
			if(node_act_type == sus_res_slave)
			{
				/* change state to previous state if node is acting as receiver */
				ft_fsm_change_state(s_sus_res_info.fsm_state_save);
				DEBUG_CPRINT(("Resumed - Write back FSM state %d \n",s_sus_res_info.fsm_state_save));
				s_sus_res_info.state = no_suspend_reusume;
				s_sus_res_info.sus_res_state_copy = state_resume;
				ft_set_timer(FTDP_WAITING_TIME_INTERVAL);
				resume_accepted_slave = 1;
			}
			else
			{
				/* change state to previous state if node is acting as receiver */
				ft_fsm_change_state(FT_Resumed);
				s_sus_res_info.state = state_resume;
				s_sus_res_info.sus_res_state_copy = state_resume;
			}

		}
		prepare_resume_request_frame(resume_type,ack_set);

		node_act_type = ft_get_master_slave_status();
		if(node_act_type == sus_res_master)
		{
			s_sus_res_info.request_clear_flag = 1;
			s_sus_res_info.sus_res_rqst_retry_count++;
			ft_set_timer(SUS_RES_RESPONSE_WAIT_SEC);
		}
		else
		{
			s_sus_res_info.request_clear_flag = 1;
			ft_set_timer(SUS_RES_RESPONSE_WAIT_SEC+2);
		}

		if(node_act_type == sus_res_slave)
		{
			if(s_sus_res_info.type != suspend_by_savecontext)
			{
				if(ft_state == ft_upload)
				{
					prepare_sts_and_notify_sender_app(transfer_resumed);
				}
				else
				{
					prepare_sts_and_notify_receiver_app(transfer_resumed);
				}
			}
		}
		else
		{

		}

	}
	else
	{
		if(resume_accepted_slave == 1)
		{
			/* Resume was accepted already, now it just send the ACK */
			DEBUG_CPRINT(("FTM Resumed Already\n"));
			resume_accepted_slave = 0;
			prepare_resume_request_frame(resume_type,ack_set);
		}
	}
	u8_ftds_rx_ctr = 0;
}




/**
 * @brief This function used to send acknowledgment for save context request
 *
 *
 * This will only send ack to other node
 */
void ft_savecontext_ack(uint8_t ack)
{

	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();

	if(ft_state == ft_upload)
	{
		if(ack == 1)
		{
			send_ftfci(ftfci_ack,0);
			s_sus_res_info.sus_savctxt_ack_sent = 1;
		}
		else
		{
			send_ftfci(ftfci_nak,0);
		}
	}
	else if(ft_state == ft_download)
	{
		if(ack == 1)
		{
			send_ftsr(ftsr_ack,0);
			s_sus_res_info.sus_savctxt_ack_sent = 1;
		}
		else
		{
			send_ftsr(ftsr_nak,0);
		}
	}
}


/**
 * @brief This handler function will handle the suspend timer expiry management
 * Suspend Resume request re try will also be handled here
 *
 * will execute both on upload and download cycles if suspend/resume request is invoked
 */
void ft_sus_res_handler(void)
{
	static uint8_t resume_time;
	uint8_t timer_flg;
	e_ft_current_process ft_state;
	e_avtive_type node_act_type;





	/* only works when node is slave to run the timeout timer*/
	node_act_type = ft_get_master_slave_status();
	if(node_act_type == sus_res_slave)
	{



		if(s_sus_res_info.request_clear_flag == 1)
		{
			/* check suspend/resume request has received response from other node */
			timer_flg = ft_get_flag();
			if(timer_flg == 1)
			{
				DEBUG_CPRINT(("Suspend/Resume not ACK in 5 seconds;\n"));
				ft_state =  get_file_transfer_state();
//				if(ft_state == ft_upload)
//				{
//					ft_acceptance_nack(prepare_sts_and_notify_sender_app);
//				}
//				else
//				{

					if(s_sus_res_info.sus_res_state_copy == state_suspend)
					{
						/*   suspend ack reveived by other side */
						ft_set_timer(s_sus_res_info.timeout_time_save );
						s_sus_res_info.request_clear_flag = 0;
						if(s_sus_res_info.type == suspend_by_savecontext)
						{
							/* we can add NOR copy start here */
							s_sus_res_info.sus_savctxt_ack_sent = 0;
							if(ft_state == ft_download)
							{
								prepare_sts_and_notify_receiver_app(transfer_suspended_savecontext_etended_sts);
							}
							else
							{
								prepare_sts_and_notify_sender_app(transfer_suspended_savecontext_etended_sts);
							}
							ft_stop_timer();
							ft_fsm_change_state(FT_Inactive);
							set_file_transfer_state(ft_process_na);
							ft_service_disable();
						}
						else
						{
							/* suspend sucess */
							if(ft_state == ft_upload)
							{
								prepare_sts_and_notify_sender_app(transfer_suspended);
							}
							else
							{
								prepare_sts_and_notify_receiver_app(transfer_suspended);
							}
						}
					}
					else
					{
						if(ft_state == ft_upload)
						{
							s_sus_res_info.request_clear_flag = 0;
						}
						else
						{
							/* NO FTDS arrived in 5 sec wait time so it is assumed that Resume ack not reached to other node
							 * it may try for next Resume retry.
							 */
							s_sus_res_info.state = s_sus_res_info.sus_res_state_copy;
							ft_acceptance_nack(prepare_sts_and_notify_receiver_app);
							ft_set_timer(s_sus_res_info.timeout_time_save);
						}

					}
			//	}
			}
		}
		else if(s_sus_res_info.state == state_suspend)
		{
			/* check suspend timeout is expired */
			timer_flg = ft_get_flag();
			if(timer_flg == 1)
			{
				DEBUG_CPRINT(("Terminate transmission\n"));
				ft_transfer_request(T_SuspendTimeout,0);
			}
		}

	}
	else if(node_act_type == sus_res_master)
	{
		if(s_sus_res_info.request_clear_flag == 1)
		{
			/* check suspend/resume request has received response from other node */
			timer_flg = ft_get_flag();
			if(timer_flg == 1)
			{
				ft_reset_timer();
				DEBUG_CPRINT(("Suspend/Resume not ACK in 5 seconds;..\n"));
				if(s_sus_res_info.sus_res_rqst_retry_count > 2)
				{
					DEBUG_CPRINT(("Suspend/Resume not ACK in 5 seconds;..\n"));
					ft_state =  get_file_transfer_state();
					if(ft_state == ft_upload)
					{
						ft_acceptance_nack(prepare_sts_and_notify_sender_app);
					}
					else
					{
						ft_acceptance_nack(prepare_sts_and_notify_receiver_app);
					}
					s_sus_res_info.sus_res_rqst_retry_count = 0;
					s_sus_res_info.rqst_retry_flag = 0;
				}
				else
				{
					s_sus_res_info.rqst_retry_flag = 1;
				}
			}
		}
	}

	/* only works when uploading is resumed by receiver node*/
	ft_state =  get_file_transfer_state();
	if(ft_state == ft_upload)
	{
		if((s_sus_res_info.state == state_resume_ack)
				|| (node_act_type == sus_res_slave && s_sus_res_info.state == state_resume))
		{
			resume_time++;
			DEBUG_CPRINT(("Ready %d... \n",resume_time));
			if(resume_time > 3)
			{
				ft_fsm_change_state(s_sus_res_info.fsm_state_save);
				s_sus_res_info.state = no_suspend_reusume;
				s_sus_res_info.request_clear_flag = 0;
			}
		}
		else
		{

		}
	}

	if(s_sus_res_info.rqst_retry_flag == 1)
	{
		if(s_sus_res_info.state == state_suspend || sus_res_dwld_side_rqst_raise == 1)
		{
			sus_res_dwld_side_rqst_raise = 0;
			DEBUG_CPRINT(("Resend ST Trial:%d... \n",s_sus_res_info.sus_res_rqst_retry_count));
			if(s_sus_res_info.type == suspend_by_savecontext)
			{
				ft_transfer_request(Suspend_Savecontext_Mode_rqst,sus_temp);
			}
			else
			{
				ft_transfer_request(Suspend_Timeout_Mode_rqst,sus_temp);
			}
		}
		else if(s_sus_res_info.state == state_resume)
		{
			DEBUG_CPRINT(("Resend RT Trial:%d... \n",s_sus_res_info.sus_res_rqst_retry_count));
			s_sus_res_info.state = state_suspend;
			if(s_sus_res_info.type == suspend_by_timeout)
			{
				ft_fsm_change_state(FT_Suspended);
				ft_transfer_request(Resume_Timeout_Mode_rqst,0);
			}
			else
			{
				ft_resume(0xff,0);
			}
		}
		s_sus_res_info.rqst_retry_flag = 0;
	}

}

/**
 * @brief This function used to set the type of node whether node as master or slave
 * It will be decided based on who initiated the suspend request
 *
 */
void ft_set_master_slave(e_avtive_type set)
{
	s_sus_res_info.active_sts = set;
}



/**
 * @brief This function used to return the node type whether the node was setted as mater or slave
 *
 *
 */
e_avtive_type ft_get_master_slave_status(void)
{
	return s_sus_res_info.active_sts;
}

/**
 * @brief This function used to terminate transmission
 *
 *
 */
void ft_cancel_ftp(void)
{
	ft_fsm_change_state(FT_Inactive);
	set_file_transfer_state(ft_process_na);
	ft_stop_timer();
}


/**
 * @brief This function used to terminate transmission
 *
 */
void ft_terminate(ft_request ter_option, uint8_t ack)
{
	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();

	if(ft_state == ft_upload)
	{
		if(ack == 1)
		{
#ifndef FT_OBC
			ft_file_close(tx_info.fptr,&tx_info.file_opened, tx_info.tx_mode);
#endif
			if(ter_option == T_SuspendTimeout)
			{
				send_ftfci(ftfci_cancelled_by_susp_timeoout,0);
				prepare_sts_and_notify_sender_app(tx_terminated_suspend_timeout_expired);
			}
			else if(ter_option == T_Txnode)
			{
				send_ftfci(ftfci_cancelled_by_txnode,0);
				prepare_sts_and_notify_sender_app(transmission_terminated_receiver_not_responsive);
			}
			else if(ter_option == Terminate_Transmission_rqst)
			{
				send_ftfci(ftfci_cancelled_by_txnode,0);
			}
		}
		else
		{

		}
	}
	else if(ft_state == ft_download)
	{
		if(ack == 1)
		{
#ifndef FT_OBC
			ft_file_close(dwnld_rqst.fptr,&dwnld_rqst.file_opened, dwnld_rqst.tx_mode);
#endif

			if(ter_option == T_SuspendTimeout)
			{
				send_ftsr(ftsr_cancelled_by_suspend_timeoout,0);
				prepare_sts_and_notify_receiver_app(tx_terminated_suspend_timeout_expired);
			}
			else if(ter_option == Terminate_Transmission_rqst)
			{
				send_ftsr(ftsr_terminate_rxnode,0);
				prepare_sts_and_notify_receiver_app(transmission_terminated_by_rx_node);
			}
			else if(ter_option == T_Rxnode)
			{
				send_ftsr(ftsr_terminate_rxnode,0);
				prepare_sts_and_notify_receiver_app(transmission_terminated_by_rx_node);
			}
		}
		else
		{

		}
	}
	ft_fsm_change_state(FT_Inactive);
	set_file_transfer_state(ft_process_na);
	ft_stop_timer();
	ft_service_disable();
}

/**
 * @brief  * This function will resume and reopen downloading file if suspend ack not delivered to requester node
 *
 * this function will resume and reopen downloading file if suspend ack not delivered to requester node
 */
void ft_check_suspend_status()
{
/*	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();
	DEBUG_CPRINT(("FTDS before clear\n"));
	DEBUG_CPRINT(("s_sus_res_info.state =%d\n",s_sus_res_info.state));
	DEBUG_CPRINT(("s_sus_res_info.type =%d\n",s_sus_res_info.type));
	DEBUG_CPRINT(("s_sus_res_info.sus_res_state_copy =%d\n",s_sus_res_info.sus_res_state_copy));
	DEBUG_CPRINT(("ft_state =%d\n",ft_state));*/
	if(s_sus_res_info.state == state_suspend)
	{
		if(s_sus_res_info.type == suspend_by_timeout)
		{
			DEBUG_CPRINT(("Sus_T Clear by FTDS\n"));
			restart_transmission_no_timer_set();
		}
		else if(s_sus_res_info.type == suspend_by_savecontext)
		{
			DEBUG_CPRINT(("Sus_Ctx Clear by FTDS\n"));
			ft_file_reopen_download();
			restart_transmission_no_timer_set();
		}
	}
	//else if(s_sus_res_info.sus_res_state_copy == state_resume)
	else if(s_sus_res_info.state == state_resume)
	{
		DEBUG_CPRINT(("Res_T Clear by FTDS\n"));
		//s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		s_sus_res_info.state = no_suspend_reusume;
		s_sus_res_info.request_clear_flag = 0;
		ft_set_timer(SENDER_RESPONSE_WAIT_TIME);
	}

	ftds_incoming_flag = 1;
}


/**
 * @brief This function used to set the suspend resume current status
 *
 */
void ft_set_suspend_resume_sts(e_sus_res_state set)
{
	 s_sus_res_info.state = set;
}


/**
 * @brief This function used to get the suspend resume current status
 *
 *
 */
e_sus_res_state ft_get_suspend_resume_sts(void)
{
	return s_sus_res_info.state;
}


e_sus_res_state ft_get_state_before_suspend(void)
{
	return s_sus_res_info.fsm_state_save;
}

#ifdef FT_SUSRES_TEST
void ft_sus_res_debug_init(void)
{
	memset(&ftm_db_test, 0xff, sizeof(ftm_db_params));
	ftm_db_test.skip_all_res_ack_ = 0;
	ftm_db_test.skip_all_sus_ack_ = 0;
	ftm_db_test.skip_all_res_req_ = 0;
	ftm_db_test.skip_all_sus_req_ = 0;
}

void ft_sus_res_debug_deinit(void)
{
	memset(&ftm_db_test, 0x00, sizeof(ftm_db_params));
}
#endif



/**
 * @brief This function used to initialize suspend resume related params
 *
 *
 */
void init_sus_res(void)
{
	s_sus_res_info.fsm_state_save =FT_Init;
	s_sus_res_info.state = no_suspend_reusume;
	s_sus_res_info.resume_time =0;
	s_sus_res_info.request_clear_flag = 0;
	s_sus_res_info.sus_res_rqst_retry_count = 0;
	s_sus_res_info.rqst_retry_flag =0;
	s_sus_res_info.sus_savctxt_ack_sent = 0;
	ftds_incoming_flag = 0;
	u8_ftds_rx_ctr = 0;
	sus_sct_avail = 0;
#ifdef FT_SUSRES_TEST
	ft_sus_res_debug_init();
#endif
}



/**
 * @brief  * This function used to clear the counters used for sus-res request failure trails
 *
 */
void clear_sus_res_req_retry_cntr(void)
{
	s_sus_res_info.sus_res_rqst_retry_count = 0;
	s_sus_res_info.rqst_retry_flag =0;
	//sus_res_timer_cnt = 0;
}




/**
 * @brief  * This function will clear sus res request if any pending request not processed in time
 *
 * this function will clear sus res request if any pending
 */
void sus_res_clear_pending_rqst(void)
{
	e_ft_current_process ft_state;
	static uint16_t sus_res_timer_cnt=0;

	if(sus_res_timer_cnt < FTDS_RX_CHECK_INTERVAL)
	{
		sus_res_timer_cnt++;
	}
	else
	{
		sus_res_timer_cnt = 0;
		if(u8_ftds_rx_ctr < 3)
		{
			if(ftds_incoming_flag == 1)
			{
				u8_ftds_rx_ctr++;
			}
			else
			{
				u8_ftds_rx_ctr = 0;
			}
			DEBUG_CPRINT(("SUS RES clear cntr %d  @@@\n",u8_ftds_rx_ctr));
		}
		else
		{
			u8_ftds_rx_ctr = 0;
			DEBUG_CPRINT(("SUS RES clear   @@@@ \n"));
			if(s_sus_res_info.state == no_suspend_reusume)
			{
				DEBUG_CPRINT(("SUS RES clear &&&  @@@@ \n"));

				if(s_sus_res_info.request_clear_flag == 1)
				{
					ft_state =  get_file_transfer_state();
					if(ft_state == ft_upload)
					{
						ft_acceptance_nack(prepare_sts_and_notify_sender_app);
					}
					else
					{
						ft_acceptance_nack(prepare_sts_and_notify_receiver_app);
					}
					s_sus_res_info.request_clear_flag = 0;
				}
				s_sus_res_info.sus_savctxt_ack_sent = 0;
			}
		}
		ftds_incoming_flag = 0;


	}
}
