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



#include "notify_apps.h"

#include "stdio.h"

#define FT_APP_MAX_LIMIT 10


typedef struct ft_app_register
{
	uint16_t app_id;
	notify_api app_api;
}s_ft_app_register;


typedef struct ft_app_list
{
	uint16_t registered_app_cnt;
	s_ft_app_register app_list[FT_APP_MAX_LIMIT];
}s_ft_app_list;



s_ft_app_list sender_apps =
{
		0,
		{
      { 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
    }
};

s_ft_app_list receiver_apps =
{
		0,
		{
      { 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
  		{ 0, NULL},
    }
};

uint8_t invoke_app_api(s_ft_app_list* apps,ft_notification_info* notify_info)
{
	uint8_t ret =0;
	uint8_t u8cnt;
	//printf("Searching App ID : %x\n",notify_info->app_id);

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		if(apps->app_list[u8cnt].app_id == notify_info->app_id)
		{
			//printf("App found\n");
			if(apps->app_list[u8cnt].app_api != NULL)
			{
				//printf("Invoking API\n");
				apps->app_list[u8cnt].app_api(notify_info);
				ret = 1;
			}
			else
			{
				printf("App FP Null !\n");
			}
			break;
		}
	}
	if(ret != 1)
	{
		printf("Error App ID:%d not registered\n",notify_info->app_id);
	}
	return ret;
}



uint8_t is_sender_app_resgistered(uint16_t input_app_id)
{
	uint8_t ret =0;
	uint8_t u8cnt;
	//printf("Searching App ID : %x\n",notify_info->app_id);

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		if(sender_apps.app_list[u8cnt].app_id == input_app_id)
		{
			//printf("App found\n");
			if(sender_apps.app_list[u8cnt].app_api != NULL)
			{
				ret = 1;
			}
			else
			{
				printf("App FP Null !\n");
			}
			break;
		}
	}
	if(ret != 1)
	{
		printf("Error App ID:%d not registered\n",input_app_id);
	}
	return ret;
}




void remove_duplicate_entry(s_ft_app_list* apps, uint16_t app_id)
{
	uint8_t u8cnt;

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		if(apps->app_list[u8cnt].app_id == app_id)
		{
			apps->app_list[u8cnt].app_api = NULL;
			apps->app_list[u8cnt].app_id = 0;
			printf("FTM App duplicated\n");
			break;
		}
	}
}


uint8_t register_apps(s_ft_app_list* apps, uint16_t app_id, notify_api app_api)
{
	uint8_t u8cnt;
	uint8_t ret =0;
	if(apps->registered_app_cnt < FT_APP_MAX_LIMIT)
	{
		remove_duplicate_entry(apps, app_id);
		for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
		{
			if(apps->app_list[u8cnt].app_api == NULL)
			{
				apps->app_list[u8cnt].app_api = app_api;
				apps->app_list[u8cnt].app_id = app_id;
				apps->registered_app_cnt++;
				ret = 1;
				printf("App ID:%d registered at %d \n",app_id,u8cnt);
				break;
			}
		}
	}
	return ret;
}

/*
 * this api receives the sender side notification function and registered with FT
 */
uint8_t ft_register_sender_app(uint16_t input_app_id, notify_api input_app_api)
{
	uint8_t ret =0;
	ret = register_apps(&sender_apps, input_app_id, input_app_api);
	return ret;
}



/*
 * this api receives the receiver side notification function and registered with FT
 */
uint8_t ft_register_receiver_app(uint16_t input_app_id, notify_api input_app_api)
{
	uint8_t ret =0;
	ret = register_apps(&receiver_apps, input_app_id, input_app_api);
	return ret;
}


uint8_t ft_notify_sender_app(ft_notification_info* notify_info)
{
	uint8_t ret =0;
	printf("\r\n-----/Sender side notify/-----\n");
	ret = invoke_app_api(&sender_apps,notify_info);
	return ret;
}


uint8_t ft_notify_receiver_app(ft_notification_info* notify_info)
{
	uint8_t ret =0;
	printf("\r\n-----/Receiver side notify-----\n");
	ret = invoke_app_api(&receiver_apps,notify_info);
	return ret;
}


void ft_init_notify()
{
	uint8_t u8cnt;
	printf("Delete notify apps register\n");

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		sender_apps.app_list[u8cnt].app_api = NULL;
		sender_apps.app_list[u8cnt].app_id = 0;
		receiver_apps.app_list[u8cnt].app_api = NULL;
		receiver_apps.app_list[u8cnt].app_id = 0;
	}
	sender_apps.registered_app_cnt = 0;
	receiver_apps.registered_app_cnt = 0;

}

void restart_transmission()
{
	ft_fsm_change_state(s_sus_res_info.fsm_state_save);
	printf("Resumed - Write back FSM state %d \n",s_sus_res_info.fsm_state_save);
	print_current_fsmstate();
	ft_set_timer(FTDP_WAITING_TIME_INTERVAL);
	s_sus_res_info.state = no_suspend_reusume;
}


void restart_transmission_no_timer_set()
{
	ft_fsm_change_state(s_sus_res_info.fsm_state_save);
	printf("Resumed - Write back FSM state %d \n",s_sus_res_info.fsm_state_save);
	print_current_fsmstate();
	//ft_set_timer(FTDP_WAITING_TIME_INTERVAL);
	s_sus_res_info.state = no_suspend_reusume;
}


void ft_acceptance_received(notify_complete_sts_fp n_fp)
{

	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();


	printf("s_sus_res_info.state =%d\n",s_sus_res_info.state);
	printf("s_sus_res_info.type =%d\n",s_sus_res_info.type);
	printf("s_sus_res_info.sus_res_state_copy =%d\n",s_sus_res_info.sus_res_state_copy);
	printf("ft_state =%d\n",ft_state);

	if( (s_sus_res_info.state == state_suspend)  ||
	  ( (s_sus_res_info.sus_res_state_copy == state_suspend) && (ft_state == ft_download) ) )
	{
		if(s_sus_res_info.type == suspend_by_timeout)
		{
			n_fp(transfer_suspend_accepted);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.state = state_suspend;
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}
		else if(s_sus_res_info.type == suspend_by_savecontext)
		{
			n_fp(transfer_suspend_savecontext_accepeted);
			clear_sus_res_req_retry_cntr();
			ft_stop_timer();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}
		else
		{

		}
	}
	else if(s_sus_res_info.state == state_resume)
	{
		if(s_sus_res_info.type == suspend_by_timeout)
		{
			restart_transmission();
			n_fp(transfer_resume_accepted);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
//			ft_fsm_change_state(s_sus_res_info.fsm_state_save);
//			printf("Resumed - Write back FSM state %d \n",s_sus_res_info.fsm_state_save);
//			print_current_fsmstate();
//			n_fp(transfer_resume_accepted);
//			ft_set_timer(FTDP_WAITING_TIME_INTERVAL);
//			s_sus_res_info.state = no_suspend_reusume;
		}
		else if(s_sus_res_info.type == suspend_by_savecontext)
		{
			restart_transmission();
			n_fp(transfer_resume_savecontext_accepeted);
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
			clear_sus_res_req_retry_cntr();
//			ft_fsm_change_state(s_sus_res_info.fsm_state_save);
//			printf("Resumed-Save Context - Write back FSM state %d \n",s_sus_res_info.fsm_state_save);
//			print_current_fsmstate();
//			n_fp(transfer_resume_savecontext_accepeted);
//			ft_set_timer(FTDP_WAITING_TIME_INTERVAL);
//			s_sus_res_info.state = no_suspend_reusume;
		}
		else
		{

		}
	}

	if(s_sus_res_info.request_clear_flag == 1)
	{
		/* clear suspend/request request flag if ack is received */
		s_sus_res_info.request_clear_flag = 0;
	}
}



void ft_acceptance_nack(notify_complete_sts_fp n_fp)
{
	e_ft_current_process ft_state;
	ft_state =  get_file_transfer_state();

	if((s_sus_res_info.state == state_suspend) ||
		  ( (s_sus_res_info.sus_res_state_copy == state_suspend) && (ft_state == ft_download) ) )
	{
		printf("Warning !!! Suspend not accepted \n");
		if(s_sus_res_info.type == suspend_by_timeout)
		{
			restart_transmission();
			n_fp(transfer_suspend_tout_not_accepted);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}
		else if(s_sus_res_info.type == suspend_by_savecontext)
		{
			restart_transmission();
			n_fp(transfer_suspend_savecontext_failed);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}
		else
		{

		}
	}
	else if(s_sus_res_info.state == state_resume)
	{
		printf("Warning !!! Resume not accepted \n");
		if(s_sus_res_info.type == suspend_by_timeout)
		{
			s_sus_res_info.state = state_suspend;
			ft_fsm_change_state(FT_Suspended);
			n_fp(transfer_rseume_tout_not_accepted);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}
		else if(s_sus_res_info.type == suspend_by_savecontext)
		{
			ft_fsm_change_state(FT_Inactive);
			set_file_transfer_state(ft_process_na);
			n_fp(transfer_resume_restorecontext_failed);
			clear_sus_res_req_retry_cntr();
			s_sus_res_info.sus_res_state_copy = no_suspend_reusume;
		}

	}

	if(s_sus_res_info.request_clear_flag == 1)
	{
		/* clear suspend/request request flag if ack is received */
		s_sus_res_info.request_clear_flag = 0;
	}
}

