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

#include "ft_upload.h"

#include "stdio.h"
#include "notify_apps.h"
#include "file_transfer.h"
#include "ft_dwnld.h"
#include "ft_config.h"
#include "upload_def.h"
#include "download_def.h"
#include "ftfci_decode.h"
#include "ftci_decode.h"
#include "segmentation.h"
#include "suspend_resume.h"
#include <unistd.h>
#include "exo_types.h"
#include "exo_common.h"

//#include "sample_app_dwnld_obc.h"



#define APP_ID 0x1234

extern uint8_t *gui_savecontext_ptr;
extern uint16 savecontext_size;

uint8_t init_start=0;


static uint8_t mode_select;
uint8_t suspend_context_activated = 0;
uint8_t file_tx_running = 0;
uint8_t RC_flag =0;

#define INPUT_BULKDAT_BUF_LEn 1024


void display_ft_sts()
{
	uint8_t percentage_upload;
	uint8_t err_code;
	 CPRINT_VARIABLE_UNUSED(percentage_upload);
	 CPRINT_VARIABLE_UNUSED(err_code);
	percentage_upload = ft_get_upload_percentage_compl();
	err_code = ft_get_error_sts();
	DEBUG_CPRINT(("\r\nFT status:  Upload Comp Percent:%d | Error Code:%d\r\n",percentage_upload,err_code));

}




/*
 *
 *  Application API which will be invoked during file transmission by FT framework
 *
 */
void app1234_notificataion_api_upld(ft_notification_info *ft_sts)
{
	uint16_t u16cnt;
	e_avtive_type node_act_type;
	uint8_t ret_sts;

	static uint8_t nack_test = 1;

	DEBUG_CPRINT(("App notification API invoked !!!!\n"));


	if(ft_sts->status == transfer_upload_success)
	{
		DEBUG_CPRINT(("1. upload success\n"));
		init_start = 0;
		//file_tx_running = 0;
	}
	else if(ft_sts->status == crc_error)
	{
		DEBUG_CPRINT(("1. upload failed/ CRC error\n"));
		init_start = 0;
		//file_tx_running = 0;

	}
	else if(ft_sts->status == transfer_suspended)
	{
		DEBUG_CPRINT(("1. upload suspended by receiver [Timeout mode]\n"));
		display_ft_sts();
	}
	else if(ft_sts->status == transfer_suspended_savecontext)
	{
		DEBUG_CPRINT(("1. upload suspended by receiver [Savecontext Mode]\n"));

		gui_savecontext_ptr = os_malloc(ft_sts->context_info.context_info_size);
		if(gui_savecontext_ptr != NULL)
		{
			savecontext_size = ft_sts->context_info.context_info_size;
			DEBUG_CPRINT(("2. context data size: %d\n",savecontext_size));
			DEBUG_CPRINT(("3. context data : "));
			for (u16cnt = 0; u16cnt < savecontext_size; u16cnt++)
			{
				gui_savecontext_ptr[u16cnt] = ft_sts->context_info.context_info_buf_ptr[u16cnt];
				//DEBUG_CPRINT(("%x ",gui_savecontext_ptr[u16cnt]));
			}
			display_context_info();

			node_act_type = ft_get_master_slave_status();
			if(node_act_type == sus_res_slave)
			{
				if(nack_test != 0)
				{
					ft_transfer_request(Suspend_Savecontext_ack_rqst,0);
					init_start = 0;
					//file_tx_running = 0;
				}
				else
				{
					ft_transfer_request(Suspend_Savecontext_nack_rqst,0);
					nack_test = 1;
				}
			}
		}
	}
	else if(ft_sts->status == transfer_resumed_restorecontext)
	{
		DEBUG_CPRINT(("1. upload resumed by receiver [Savecontext Mode]\n"));
		ret_sts = ft_resume_context(gui_savecontext_ptr,savecontext_size);
		if(ret_sts == 0)
		{
			os_free(gui_savecontext_ptr);
			gui_savecontext_ptr = NULL;
			//init_start = 1;
		}
		else
		{
			DEBUG_CPRINT(("Resume-SaveContext Error %d\n",ret_sts));
		}
	}
	else if(ft_sts->status == transfer_resumed)
	{
		DEBUG_CPRINT(("1. upload resumed back by receiver\n"));
	}
	else if(ft_sts->status == tx_terminated_suspend_timeout_expired)
	{
		DEBUG_CPRINT(("1. upload Terminated due to suspend timeout expired\n"));
		init_start = 0;
		//file_tx_running = 0;

	}
	else if(ft_sts->status == transfer_suspend_accepted)
	{
		DEBUG_CPRINT(("1. upload Suspend - Timeout mode Accepted by Receiver\n"));
		display_ft_sts();
	}
	else if(ft_sts->status == transfer_suspend_savecontext_accepeted)
	{
		DEBUG_CPRINT(("1. upload Suspend - Save context mode Accepted by Receiver\n"));

		gui_savecontext_ptr = os_malloc(ft_sts->context_info.context_info_size);
		if(gui_savecontext_ptr != NULL)
		{
			savecontext_size = ft_sts->context_info.context_info_size;
			DEBUG_CPRINT(("2. context data size: %d\n",savecontext_size));
			DEBUG_CPRINT(("3. context data : "));
			for (u16cnt = 0; u16cnt < savecontext_size; u16cnt++)
			{
				gui_savecontext_ptr[u16cnt] = ft_sts->context_info.context_info_buf_ptr[u16cnt];
				//DEBUG_CPRINT(("%x ",gui_savecontext_ptr[u16cnt]));
			}
			display_context_info();

			node_act_type = ft_get_master_slave_status();
			if(node_act_type == sus_res_slave)
			{
				if(nack_test != 0)
				{
					ft_transfer_request(Suspend_Savecontext_ack_rqst,0);
				}
				else
				{
					/* send NACK to check suspend context is aborted */
					ft_transfer_request(Suspend_Savecontext_nack_rqst,0);
					nack_test = 1;
				}
			}
			else
			{
				/* go back to input mode to intaite another FT */
				init_start = 0;
				//file_tx_running = 0;

				display_ft_sts();
			}
		}
	}
	else if(ft_sts->status == transfer_resume_accepted)
	{
		DEBUG_CPRINT(("1. upload Resume - Timeout mode Accepted by Receiver\n"));
	}
	else if(ft_sts->status == transfer_resume_savecontext_accepeted)
	{
		DEBUG_CPRINT(("1. upload Resume - Savecontext mode Accepted by Receiver\n"));
		init_start = 1;
	}
	else if(ft_sts->status == transfer_upload_ready)
	{
		DEBUG_CPRINT(("1. Receiver ready for Download\n"));
	}
	else if(ft_sts->status == invalid_receiver_app_id)
	{
		DEBUG_CPRINT(("1. Upload request cancelled - Receiver API not registered !!!\n"));
		init_start = 0;
		//file_tx_running = 0;
	}
	else if(ft_sts->status == transfer_upload_rejected)
	{
		DEBUG_CPRINT(("1. Upload request rejected - Issue in FTCI decoding in Rx node !!!\n"));
		init_start = 0;
	}
	else if(ft_sts->status == transmission_terminated_receiver_not_responsive)
	{
		DEBUG_CPRINT(("1. Upload Terminated due to Receiver not responsive !!!\n"));
		init_start = 0;
		//file_tx_running = 0;
	}
	else if(ft_sts->status == transmission_terminated_by_rx_node)
	{
		DEBUG_CPRINT(("1. download Terminated by Receiver node\n"));
		init_start = 0;
	}
	else if(ft_sts->status == transfer_suspend_tout_not_accepted)
	{
		DEBUG_CPRINT(("1. suspend timeout request not completed\n"));
	}
	else if(ft_sts->status == transfer_suspend_savecontext_failed)
	{
		DEBUG_CPRINT(("1. suspend savecontext request not completed\n"));
	}
	else if(ft_sts->status == transfer_rseume_tout_not_accepted)
	{
		DEBUG_CPRINT(("1. resume timeout request not completed\n"));
	}
	else if(ft_sts->status == transfer_resume_restorecontext_failed)
	{
		DEBUG_CPRINT(("1. resume savecontext request not completed\n"));
	}
	else
	{
		DEBUG_CPRINT(("Invalid Notification not processed\n"));

	}

	DEBUG_CPRINT(("\n-------------/End/---------------\n\n"));

}





static uint8_t get_ft_input()
{
	uint16_t mtu;
	uint8_t ret_sts;
	char loc_str[50];

	DEBUG_CPRINT(("\r\nEnter input file name\r\n"));
	scanf("%s",loc_str);
	ret_sts = ft_config_sender_file_name_path(loc_str);
	if (ret_sts != 1)
	{
		return 0;
	}

	DEBUG_CPRINT(("\r\nEnter MTU size in bytes\r\n"));
	scanf("%hu", &mtu);
	DEBUG_CPRINT(("MTU size set: %u\r\n", mtu));
	ft_config_mtu_size(mtu);
	ft_transfer_request(Start_Transmission_rqst,0);
	return ret_sts;
}



static uint8_t get_bulk_data_input()
{
	uint16_t mtu;
	uint8_t ret_sts=1;

	DEBUG_CPRINT(("\r\nInput buffer \"bulk_data_buffer\" selected\r\n"));
	ft_config_bulk_data_input_buffer(NULL,INPUT_BULKDAT_BUF_LEn);

	DEBUG_CPRINT(("\r\nEnter MTU size in bytes\r\n"));
	scanf("%hu", &mtu);
	DEBUG_CPRINT(("MTU size set: %u\r\n", mtu));
	ft_config_mtu_size(mtu);
	ft_transfer_request(Start_Transmission_rqst,0);
	return ret_sts;
}








void debug_inputHandler(void)
{
	uint8_t ret=0;

	if (mode_select == 0)
	{
		while(ret ==0)
		{
			ret = get_ft_input();
		}
	}
	else if (mode_select == 1)
	{

		while(ret ==0)
		{
			ret = get_bulk_data_input();
		}

	}
}






void debug_select_mode()
{
	uint8_t ret=0;
	char input_str[50] = "FILE";

	while(ret == 0)
	{
		DEBUG_CPRINT(("\r\nEnter Mode >> FILE or DATA ?\r\n"));
		scanf("%s",input_str);
		if (strcmp(input_str, "FILE") == 0)
		{
			DEBUG_CPRINT(("File mode selected\r\n"));
			ret = ft_mode_select(0);
			mode_select = 0;
		}
		else if (strcmp(input_str, "DATA") == 0)
		{
			DEBUG_CPRINT(("Bulk data mode selected\r\n"));
			ft_mode_select(1);
			ret = 1;
			mode_select = 1;
		}
		else
		{
			DEBUG_CPRINT(("Invalid mode, Enter again\r\n"));
		}

	}

}



void app1234_file_transfer_initiate(void)
{
	uint8_t ret=0;
	char input[5];
	RC_flag = 0;
	while(ret == 0)
	{
		DEBUG_CPRINT(("\r\nSelect Node >> SENDER or RECEIVER ?\n"));
		DEBUG_CPRINT(("	Enter SEN to work as SENDER node\n"));
		DEBUG_CPRINT(("	Enter RCV to work as RECEIVER node\n"));
		DEBUG_CPRINT(("	Enter RCT to Restore Context of previous FT session if any\n"));
		DEBUG_CPRINT(("	Enter EX  to exit from FT\n"));


		scanf("%s",input);
		if (strcmp(input, "SEN") == 0)
		{
			DEBUG_CPRINT(("SENDER selected\r\n"));

			ret = ft_register_sender_app(APP_ID, app1234_notificataion_api_upld);
			if(ret != 0)
			{
				ft_config_app_id(APP_ID);
		//		ft_mode_select("FILE");
		//		ft_get_sender_file_name_path("file1.txt");
		//		ft_get_mtu_size(250);
		//		ft_transfer_request(Start_Transmission_rqst,0);

				debug_select_mode();
				debug_inputHandler();
			}
		}
		else if (strcmp(input, "RCV") == 0)
		{
			DEBUG_CPRINT(("RECEIVER selected\r\n"));

			sample_app_regisration_dwld();
			ret = 1;
			init_start = 1;
		}
		else if (strcmp(input, "RCT") == 0)
		{
			RC_flag = 1;
			ret = 1;
			init_start = 1;
		}
		else if (strcmp(input, "EX") == 0)
		{
			ret = 1;
			file_tx_running = 0;
		}
		else
		{
			ret = 0;
		}
	}

}



void app1234_thread(void)
{
	char input_str[50] = "FILE";
	e_ft_current_process ft_state;
	uint8_t timeout;
	file_tx_running= 1;
	uint8_t ret_sts;


	while(1)
	{
		if(file_tx_running == 0)
		{
			break;
		}
		os_delay(2000);

		if(init_start == 0)
		{
			app1234_file_transfer_initiate();

			DEBUG_CPRINT(("\r\nEnter interrupt options\n"));
			DEBUG_CPRINT(("1. \"STxx\" >> Suspend with timeout mode , here \"xx\" denotes timeout value in range 10-99 in seconds\n"));
			DEBUG_CPRINT(("2. \"RT\"   >> Resume - timeout mode\n"));
			DEBUG_CPRINT(("3. \"SCT\"  >> Suspend with savecontext mode\n"));
		//	DEBUG_CPRINT(("4. /"RC/" >> Resume with savecontext mode\n"));
		}

		ft_state =  get_file_transfer_state();
		if(ft_state != ft_process_na || init_start != 0)
		{
			init_start = 1;

			if(RC_flag != 1)
			{
				scanf("%s",input_str);
			}
			else
			{
				input_str[0] = 'R';
				input_str[1] = 'C';
				input_str[2] = 'T';
				input_str[3] = '\0';
				RC_flag = 0;
			}

			if(ft_state != ft_process_na || suspend_context_activated == 1)
			{

				if ((input_str[0] == 'S') && (input_str[1] == 'T'))
				{
					timeout = ((input_str[2]-48)*10) + (input_str[3]-48);
					if(timeout > 99)
					{
						timeout = 20;
					}
					DEBUG_CPRINT(("\r\nSuspend-Timeout mode selected - %d seconds\r\n",timeout));
					ft_transfer_request(Suspend_Timeout_Mode_rqst,timeout);
				}
				else if (strcmp(input_str, "RT") == 0)
				{
					DEBUG_CPRINT(("\r\nResume-Timeout mode selected \r\n"));
					ft_transfer_request(Resume_Timeout_Mode_rqst,0);
				}
				else if (strcmp(input_str, "SCT") == 0)
				{
					DEBUG_CPRINT(("\r\nSuspend-SaveContext mode selected \r\n"));
					/*
					 * here the timeout time will be used by other node
					 */
					ft_transfer_request(Suspend_Savecontext_Mode_rqst,20);
					suspend_context_activated = 1;
				}
				else if (strcmp(input_str, "RCT") == 0)
				{
					DEBUG_CPRINT(("\r\nResume-Context mode selected \r\n"));
					ft_contextsave_info *c_inf = (ft_contextsave_info*)gui_savecontext_ptr;
					if(c_inf->tx_mode == 1)
					{
						DEBUG_CPRINT(("\r\nResume-SaveContext mode [Bulkdata] selected \r\n"));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
						DEBUG_CPRINT(("Mem address passing 0x%lux of size %lu \n",c_inf->bulkdata_mem_addr,c_inf->bulkdata_len));
#pragma GCC diagnostic pop
						ft_config_bulk_data_input_buffer((uint8_t*)c_inf->bulkdata_mem_addr,(uint16_t)c_inf->bulkdata_len);
					}
					else
					{
						DEBUG_CPRINT(("\r\nResume-SaveContext mode [File] selected \r\n"));
					}
					ret_sts = ft_resume_context(gui_savecontext_ptr,savecontext_size);
					if(ret_sts == 0)
					{
						suspend_context_activated = 0;
						init_start = 1;
					}
					else
					{
						DEBUG_CPRINT(("Resume-SaveContext Error %d\n",ret_sts));

					}
				}
				else if (strcmp(input_str, "TT") == 0)
				{
					DEBUG_CPRINT(("\r\nTerminate transmission selected \r\n"));
					ft_transfer_request(Terminate_Transmission_rqst,0);
					init_start = 0;
				}
				else if (strcmp(input_str, "FS") == 0)
				{
					display_ft_sts();

				}
				else
				{
					DEBUG_CPRINT(("\r\nInvalid suspend/resume selection \r\n"));

				}
			}
			else
			{
				DEBUG_CPRINT(("No ongoing transmission..\n"));
			}



		}
	}
}



void sender_app_regist(void)
{
	ft_register_sender_app(APP_ID, app1234_notificataion_api_upld);
}


uint8_t get_ft_running_sts(void)
{
	return file_tx_running;
}
