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

#include "ft_dwnld.h"
#include "ft_upload.h"
#include "exo_common.h"


#include "stdio.h"
#include "file_transfer.h"
#include "ftfci_decode.h"
#include "ftci_decode.h"
#include "segmentation.h"
#include "notify_apps.h"

#ifndef LINUX_TEMP_PORT
#include "stm32f7xx_hal_ext.h"
#endif

/** This need to be referenced from Linker script */
#define SDRAM_BANK_ADDR_DWLD                 ((uint32_t)0xC0000000)

#define APP_ID 0x1234


extern uint8_t init_start;
extern uint8_t file_tx_running;

#ifdef FT_OBC
uint8_t *gui_savecontext_ptr;
uint16 savecontext_size;
ft_obc_payload ft_pld_obc;


uint8_t obc_flash_handler_busycheck()
{
	//return ft_pld_obc.write_request;
	return 1;

}


void Flash_Write_Data_linux (ptr_typ write_addr, uint8_t Data)
{
	uint8_t *flash_address;
	flash_address = (uint8_t*)write_addr;
	*flash_address = Data;
}



void obc_flash_write_handler(void)
{
	ptr_typ mem_offset;
	if(ft_pld_obc.write_request != 0)
	{

		DEBUG_CPRINT(("F%d,",ft_pld_obc.payload_index_inc));

		if(ft_pld_obc.payload_index_inc < ft_pld_obc.payload_len)
		{
			mem_offset = ft_pld_obc.mem_add + ft_pld_obc.payload_index_inc;
			Flash_Write_Data_linux(mem_offset,ft_pld_obc.payload_ptr[ft_pld_obc.payload_index_inc]);
			ft_pld_obc.payload_index_inc++;
		}
		else
		{
			DEBUG_CPRINT(("\n"));
			ft_pld_obc.write_request = 0;
		}
	}
}




uint8_t ft_payload_obc_sdram(uint32_t mem_address, uint8_t *payload_ptr, uint16_t payload_len)
{
	uint8_t ret_busy_sts = 0;
	uint16_t u16cnt;
	if(payload_ptr != NULL)
	{
		  for (u16cnt = 0; u16cnt < payload_len; u16cnt = u16cnt+1)
		  {
#ifndef LINUX_TEMP_PORT
			*(__IO uint8_t*) (mem_address + u16cnt) = payload_ptr[u16cnt];
#else
                        DEBUG_CPRINT(("Linux handling pending"));
#endif
		  }
		  ret_busy_sts = 1;
	}
	return ret_busy_sts;
}




uint8_t ft_payload_obc(uint64_t mem_address, uint8_t *payload_ptr, uint16_t payload_len)
{
	uint8_t ret_busy_sts = 0;
	uint16_t u16cnt;
	if(payload_ptr != NULL)
	{
		if(ft_pld_obc.write_request != 1)
		{
			ft_pld_obc.payload_ptr = os_malloc(payload_len);
			if(ft_pld_obc.payload_ptr != NULL)
			{
				for(u16cnt = 0; u16cnt< payload_len; u16cnt++)
				{
					ft_pld_obc.payload_ptr[u16cnt] = payload_ptr[u16cnt];
				}
				ft_pld_obc.mem_add = mem_address;
				ft_pld_obc.payload_len = payload_len;
				ft_pld_obc.payload_index_inc = 0;
				ft_pld_obc.write_request = 1;
				ret_busy_sts = 1;
			}
		}
	}
	return ret_busy_sts;
}



uint64_t obc_file_memory_alloc(uint16_t mem_size)
{
	uint64_t mem_ptr;
//	mem_ptr = (uint64_t)os_malloc(mem_size);
	mem_ptr = SDRAM_BANK_ADDR_DWLD;
	if(mem_ptr != 0)
	{

	}

	return (uint64_t)mem_ptr;
}


#endif



void display_context_info()
{
	ft_contextsave_info *c_info;
	//s_transfer_info* t_info;
	//s_segment_info* s_info;
	uint16_t u16cnt;
	uint16_t calc_buf_size;

	 CPRINT_VARIABLE_UNUSED(calc_buf_size);
	 CPRINT_VARIABLE_UNUSED(u16cnt);
	c_info = (ft_contextsave_info*) gui_savecontext_ptr;
	if(c_info->node_operation == ft_upload)
	{

		calc_buf_size = sizeof(ft_contextsave_info);
		//t_info = (s_transfer_info*) &gui_savecontext_ptr[calc_buf_size];

		calc_buf_size = sizeof(ft_contextsave_info) + sizeof(s_transfer_info);
		//s_info = (s_segment_info*) &gui_savecontext_ptr[calc_buf_size];

		calc_buf_size = sizeof(ft_contextsave_info) + sizeof(s_transfer_info) + sizeof(s_segment_info);
		//DEBUG_CPRINT(("\nFile name saved:size:%d | %d\n",c_info->file_name_size,c_info->file_name_size));

	}
	else
	{
		calc_buf_size = sizeof(ft_contextsave_info) + sizeof(s_treceive_info);
		//DEBUG_CPRINT(("\nFile name saved:size:%d | %d\n",c_info->file_name_size,dwnld_rqst.file_name_buf_length));

	}

	for (u16cnt = 0; u16cnt < c_info->file_name_size; u16cnt++)
	{
		DEBUG_CPRINT(("%c",gui_savecontext_ptr[calc_buf_size+u16cnt]));
	}
}





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

#ifdef FT_OBC
	uint64_t mem_address_alloc;
#endif

	static uint8_t nack_test = 1;

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

	if(ft_sts->status == transfer_download_success)
	{
		DEBUG_CPRINT(("1. download success\n"));
		if(ft_sts->dwld_info.tx_mode == 1)
		{
			DEBUG_CPRINT(("2. Transfer mode : DATA\n"));
			DEBUG_CPRINT(("3. Bulkdata received :"));

			for (u16cnt = 0; u16cnt < ft_sts->dwld_info.size_file_or_data; u16cnt++)
			{
				DEBUG_CPRINT(("%d,",ft_sts->dwld_info.bulkdata_ptr[u16cnt]));
			}
			DEBUG_CPRINT(("\n"));
		}
		else
		{
			DEBUG_CPRINT(("2. Transfer mode : FILE\n"));
			DEBUG_CPRINT(("3. File Stored path : "));
			for (u16cnt = 0; u16cnt < ft_sts->dwld_info.path_filename_buf_length; u16cnt++)
			{
				DEBUG_CPRINT(("%c",ft_sts->dwld_info.storage_path_and_File_name[u16cnt]));
			}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT(("\n4. File size : %lu",ft_sts->dwld_info.size_file_or_data));
#pragma GCC diagnostic pop
#ifdef FT_OBC
			DEBUG_CPRINT(("\n5. Bin data: \n"));
			for (u16cnt = 0; u16cnt < ft_sts->dwld_info.size_file_or_data; u16cnt++)
			{
				DEBUG_CPRINT(("%c",ft_sts->dwld_info.bulkdata_ptr[u16cnt]));
			}
			DEBUG_CPRINT(("\n"));
#endif
		}
		init_start = 0;
	//	file_tx_running = 0;


	}
	else if(ft_sts->status == crc_error)
	{
		DEBUG_CPRINT(("1. download failed/ CRC error\n"));
		if(ft_sts->dwld_info.tx_mode == 1)
		{
			DEBUG_CPRINT(("2. Transfer mode : DATA\n"));
		}
		init_start = 0;
	//	file_tx_running = 0;

	}
	else if(ft_sts->status == transfer_suspended)
	{
		DEBUG_CPRINT(("1. download suspended by sender [Timeout mode]\n"));
	//	display_ft_sts();

	}
	else if(ft_sts->status == transfer_suspended_savecontext)
	{
		DEBUG_CPRINT(("1. download suspended by sender [Save Context Mode]\n"));
		DEBUG_CPRINT(("1. malloc req: %d \n",ft_sts->context_info.context_info_size));
		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]));
			}
			/* send ack */

			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)
	{
		DEBUG_CPRINT(("1. downloading resumed by sender\n"));
	}
	else if(ft_sts->status == transfer_resume_accepted)
	{
		DEBUG_CPRINT(("1. downloading resumed back by sender\n"));
	}
	else if(ft_sts->status == tx_terminated_suspend_timeout_expired)
	{
		DEBUG_CPRINT(("1. download 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. download Suspend - Timeout mode Accepted by Sender\n"));
	//	display_ft_sts();

	}
	else if(ft_sts->status == transfer_suspend_savecontext_accepeted)
	{
		DEBUG_CPRINT(("1. Download Suspend - SaveContext mode Accepted by Sender\n"));
		DEBUG_CPRINT(("1. malloc req: %d \n",ft_sts->context_info.context_info_size));

		gui_savecontext_ptr = os_malloc(ft_sts->context_info.context_info_size);
		if(gui_savecontext_ptr != NULL)
		{

		}

	}
	else if(ft_sts->status == transfer_resumed_restorecontext)
	{
		DEBUG_CPRINT(("1. Download Resume Savecontext mode Requested by Sender\n"));


		DEBUG_CPRINT(("\r\nResume-SaveContext mode [Bulkdata] selected \r\n"));
		ft_contextsave_info *c_inf = (ft_contextsave_info*)gui_savecontext_ptr;

		if(c_inf->tx_mode == 1)
		{
#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_receiver_node_storage_address(c_inf->bulkdata_mem_addr);
		}



		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_download_ready)
	{
		DEBUG_CPRINT(("1. Download request received\n"));
		if(ft_sts->dwld_info.tx_mode == 1)
		{
			DEBUG_CPRINT(("2. Transfer mode : DATA\n"));
		}
		else
		{
			DEBUG_CPRINT(("2. Transfer mode : FILE\n"));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT(("3. File size: %lu\n",ft_sts->dwld_info.size_file_or_data));
#pragma GCC diagnostic pop
#ifdef FT_OBC
			mem_address_alloc = obc_file_memory_alloc(ft_sts->dwld_info.size_file_or_data);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT(("[OBC] Allocated memory for binary file, addr:0x%lux\n",mem_address_alloc));
#pragma GCC diagnostic pop
			ft_config_receiver_node_storage_address(mem_address_alloc);
#else
			ft_config_receiver_node_storage_address(0x12345678);
#endif
		}
	}
	else if(ft_sts->status == transfer_resume_savecontext_accepeted)
	{
		DEBUG_CPRINT(("1. download Resume - Savecontext mode Accepted by Sender\n"));
		init_start = 1;
	}
	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_otsu)
	{

	}
	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 savecontxt 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 savecontxt request not completed\n"));
	}
	else
	{
		DEBUG_CPRINT(("Invalid Notification not processed\n"));
	}

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


}



void sample_app_regisration_dwld(void)
{
	uint8_t ret;

	ret = ft_register_receiver_app(APP_ID, app1234_notificataion_api_dwld);

	if(ret != 0)
	{
		DEBUG_CPRINT(("Receiver app registered\n"));
	}
	else
	{
		DEBUG_CPRINT(("Receiver app registration failed\n"));
	}

}






