/******************************************************************************/
/**
 * @file otsu_shutdown.c
 *
 * @brief This file contains functions that provides demonstration of
 *        usage of shutdown APIs
 *
 * The functions provided in the file provides demonstration on
 * usage of shutdown APIs
 *
 * @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.
 */
/******************************************************************************/




/******************************************************************************/
/*                      Include headers of the module                      */
/******************************************************************************/


#include "otsu_shutdown.h"
#include "stddef.h"
#include "stdio.h"
#include "otsu.h"
#include "exo_osal.h"
#include "exo_common.h"
#include "logger.h"
#include "exo_tctm_ipc.h"


/******************************************************************************/
/*                  Definition of local macros                 				  */
/******************************************************************************/

#define FT_APP_MAX_LIMIT 5


/******************************************************************************/
/*          Definition of local types (typedef, enum, struct, union)          */
/******************************************************************************/

/*
 * @brief App registration info
 */
typedef struct otsu_app_register
{
	uint16_t app_id;
	uint8_t notif_sent;
	shut_notify_api app_api;
}s_otsu_app_register;


/*
 * @brief App register
 */
typedef struct shtdwn_app_list
{
	uint16_t registered_app_cnt;
	uint16_t shutdwon_timeout_time;
	s_otsu_app_register app_list[FT_APP_MAX_LIMIT];
}s_shtdwn_app_list;


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


static s_shtdwn_app_list obc_apps_shtdwn;
static os_timer_handle_ptr  otsu_shtdwn_timer;

static void firmware_shtdwn_wtg_tmr_expiry(void);
static void firmware_shtdwn_wtg_tmr_expiry(void)
{
	os_itc_msg_handle_t send_msg;

	send_msg.src_entity	 	= OBC_OTSU;
	send_msg.pld_info 		= 0;
	send_msg.Msg_id 		   = OTSU_OBC_HANDSHAKE_DONE;
	send_msg.Msg_len 		   = 0;
	send_msg.pld.pld_ptr 	= NULL;

    os_itc_msg_send(&send_msg,OBC_OTSU, os_send_itc_wait);
}


#if EN_APP_REG


static uint8_t invoke_app_api(s_shtdwn_app_list* apps,uint16_t shtdwn_timeout)
{
	uint8_t ret =0;
	uint8_t u8cnt;
	DEBUG_CPRINT(("Searching Apps.. \n"));

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		if(apps->app_list[u8cnt].app_id != 0)
		{
			DEBUG_CPRINT(("App found\n"));
			if(apps->app_list[u8cnt].notif_sent != 0)
			{
				if(apps->app_list[u8cnt].app_api != NULL)
				{
					DEBUG_CPRINT(("Invoking API\n"));
					apps->app_list[u8cnt].notif_sent = apps->app_list[u8cnt].app_api(shtdwn_timeout);
					ret = 1;
				}
				else
				{
					DEBUG_CPRINT(("App FP Null !\n"));
				}
			}
		}
	}
	if(ret != 1)
	{
		DEBUG_CPRINT(("Error App not registered\n"));

	}
	return ret;
}






static void shtdwn_app_remove_duplicate_entry(s_shtdwn_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;
			apps->app_list[u8cnt].notif_sent = 0;
			DEBUG_CPRINT(("app duplicated\n"));
			break;
		}
	}
}


uint8_t otsu_register_apps(s_shtdwn_app_list* apps, uint16_t app_id, shut_notify_api app_api)
{
	uint8_t u8cnt;
	uint8_t ret =0;
	if(apps->registered_app_cnt < FT_APP_MAX_LIMIT)
	{
		shtdwn_app_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->app_list[u8cnt].notif_sent =1;
				apps->registered_app_cnt++;
				ret = 1;
				DEBUG_CPRINT(("app registered at %d \n",u8cnt));
				break;
			}
		}
	}
	return ret;
}

/*
 * this api receives the sender side notification function and registered with FT
 */
uint8_t otsu_register_shutdwn_notify(uint16_t input_app_id, shut_notify_api input_app_api)
{
	uint8_t ret =0;
	ret = otsu_register_apps(&obc_apps_shtdwn, input_app_id, input_app_api);
	return ret;
}




uint8_t otsu_publish_shutdwn_msg_to_apps(uint16_t shtdwn_timeout)
{
	uint8_t ret =0;
	DEBUG_CPRINT(("\r\n-----/Shutdown  publish/-----\n"));
	/*
	 * Invoke all API who has regsitered shutdown notificataion
	 */
	ret = invoke_app_api(&obc_apps_shtdwn,shtdwn_timeout);
	return ret;
}



void otsu_init_obc_shutdwn_notify()
{
	uint8_t u8cnt;
	//DEBUG_CPRINT(("Delete shutdown notify apps was registered\n"));

	for (u8cnt = 0; u8cnt < FT_APP_MAX_LIMIT; u8cnt++)
	{
		obc_apps_shtdwn.app_list[u8cnt].app_api = NULL;
		obc_apps_shtdwn.app_list[u8cnt].app_id = 0;
		obc_apps_shtdwn.app_list[u8cnt].notif_sent =0;
	}
	obc_apps_shtdwn.registered_app_cnt = 0;
	obc_apps_shtdwn.shutdwon_timeout_time= 10;

}
#endif


/******************************************************************************/
/*                      Definition of global functions                        */
/******************************************************************************/



/**
* @brief This function used to set shutdown time
*
*/
void shtdwn_time_config(uint16_t time)
{
	DEBUG_CPRINT(("OTSU shtdwn time config %d\n", time));
	obc_apps_shtdwn.shutdwon_timeout_time= time;
}

/**
* @brief This is the callback function which will be invoked by RTC timer for scheduled boot purpose
* (this callback is only for testing purpose)
*/
void shtdwn_rtc_time_expired_cb(void)
{
	e_otsu_fw_update_man state = get_otsu_state();
	DEBUG_CPRINT(("\nRTC fired.."));
	if(state == e_otsu_postponed_rtc_ruinning)
	{
		otsu_state_change(e_otsu_shutdown_publish);
	}
}


/**
* @brief This is the callback function which will be invoked by shutdown timer
*/
void shtdwn_timeout_expired_cb(void *args)
{
	otsu_state_change(e_otsu_shutdown_timeout_expired);
	firmware_shtdwn_wtg_tmr_expiry();
}


/**
* @brief This function used to start the os timer
*
*
*/
void shtdwn_timer_trig(void)  //timer in seconds
{
	DEBUG_CPRINT(("SHUT_TIMER:%d\n",obc_apps_shtdwn.shutdwon_timeout_time));
	log_id_with_one_arg(LOG_INFO_L1,LOG_OTSU,SHUT_TIMER__u16_,obc_apps_shtdwn.shutdwon_timeout_time);
	if(obc_apps_shtdwn.shutdwon_timeout_time < 60)
	{
		obc_apps_shtdwn.shutdwon_timeout_time = 60;
	}
   os_timer_start(otsu_shtdwn_timer,(os_tick_time_t)obc_apps_shtdwn.shutdwon_timeout_time *1000);
}

/**
* @brief This function used to initialise the os timer
*/
void shtdwn_timer_init(void)
{
   //timer to create interrupt once at specified interval
     os_timer_create(&otsu_shtdwn_timer,"otsu_shtdwn_tmr_evnt",ONESHOT,shtdwn_timeout_expired_cb,NULL);
}

/**
* @brief This function used to de initialise the os timer
*/
void shtdwn_timer_deinit(void)
{
      os_timer_stop(otsu_shtdwn_timer);
}

