/*
 * Copyright (c) 2017 Oticon A/S
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * Reduced set of HW models sufficient to run some of the sample apps
 * and regression tests
 */

#include <stdint.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <pthread.h>
#include "hw_models_top.h"
#include "timer_model.h"
#include "irq_ctrl.h"
#include "posix_board_if.h"
#include "hw_counter.h"
#include <arch/posix/posix_soc_if.h>
#include "posix_arch_internal.h"
#include "sdl_events.h"
#include <sys/util.h>


static uint64_t simu_time; /* The actual time as known by the HW models */
static uint64_t end_of_time = NEVER; /* When will this device stop */

/* List of HW model timers: */
extern uint64_t hw_timer_timer; /* When should this timer_model be called */
extern uint64_t irq_ctrl_timer;
extern uint64_t hw_counter_timer;
#ifdef CONFIG_HAS_SDL
extern uint64_t sdl_event_timer;
#endif

static enum {
	HWTIMER = 0,
	IRQCNT,
	HW_COUNTER,
#ifdef CONFIG_HAS_SDL
	SDLEVENTTIMER,
#endif
	NUMBER_OF_TIMERS,
	NONE
} next_timer_index = NONE;

static uint64_t *Timer_list[NUMBER_OF_TIMERS] = {
	&hw_timer_timer,
	&irq_ctrl_timer,
	&hw_counter_timer,
#ifdef CONFIG_HAS_SDL
	&sdl_event_timer,
#endif
};

static uint64_t next_timer_time;

/* Have we received a SIGTERM or SIGINT */
static volatile sig_atomic_t signaled_end;

/**
 * Handler for SIGTERM and SIGINT
 */
void hwm_signal_end_handler(int sig)
{
	signaled_end = 1;
}

/**
 * Set the handler for SIGTERM and SIGINT which will cause the
 * program to exit gracefully when they are received the 1st time
 *
 * Note that our handler only sets a variable indicating the signal was
 * received, and in each iteration of the hw main loop this variable is
 * evaluated.
 * If for some reason (the program is stuck) we never evaluate it, the program
 * would never exit.
 * Therefore we set SA_RESETHAND: This way, the 2nd time the signal is received
 * the default handler would be called to terminate the program no matter what.
 *
 * Note that SA_RESETHAND requires either _POSIX_C_SOURCE>=200809 or
 * _XOPEN_SOURCE>=500
 */
void hwm_set_sig_handler(void)
{
	struct sigaction act;

	act.sa_handler = hwm_signal_end_handler;
	PC_SAFE_CALL(sigemptyset(&act.sa_mask));

	act.sa_flags = SA_RESETHAND;

	PC_SAFE_CALL(sigaction(SIGTERM, &act, NULL));
	PC_SAFE_CALL(sigaction(SIGINT, &act, NULL));
}


static void hwm_sleep_until_next_timer(void)
{
	if (next_timer_time >= simu_time) { /* LCOV_EXCL_BR_LINE */
		simu_time = next_timer_time;
	} else {
		/* LCOV_EXCL_START */
		posix_print_warning("next_timer_time corrupted (%"PRIu64"<= %"
				PRIu64", timer idx=%i)\n",
				(uint64_t)next_timer_time,
				(uint64_t)simu_time,
				next_timer_index);
		/* LCOV_EXCL_STOP */
	}

	if (signaled_end || (simu_time > end_of_time)) {
		posix_print_trace("\nStopped at %.3Lfs\n",
				((long double)simu_time)/1.0e6);
		posix_exit(0);
	}
}


/**
 * Find in between all timers which is the next one
 * and update  next_timer_* accordingly
 */
void hwm_find_next_timer(void)
{
	next_timer_index = 0;
	next_timer_time  = *Timer_list[0];

	for (unsigned int i = 1; i < NUMBER_OF_TIMERS ; i++) {
		if (next_timer_time > *Timer_list[i]) {
			next_timer_index = i;
			next_timer_time = *Timer_list[i];
		}
	}
}

/**
 * Entry point for the HW models
 * The HW models execute in an infinite loop until terminated
 */
void hwm_main_loop(void)
{
	while (1) {
		hwm_sleep_until_next_timer();

		switch (next_timer_index) { /* LCOV_EXCL_BR_LINE */
		case HWTIMER:
			hwtimer_timer_reached();
			break;
		case IRQCNT:
			hw_irq_ctrl_timer_triggered();
			break;
		case HW_COUNTER:
			hw_counter_triggered();
			break;
#ifdef CONFIG_HAS_SDL
		case SDLEVENTTIMER:
			sdl_handle_events();
			break;
#endif
		default:
			/* LCOV_EXCL_START */
			posix_print_error_and_exit(
					"next_timer_index corrupted\n");
			break;
			/* LCOV_EXCL_STOP */
		}

		hwm_find_next_timer();
	}
}

/**
 * Set the simulated time when the process will stop
 */
void hwm_set_end_of_time(uint64_t new_end_of_time)
{
	end_of_time = new_end_of_time;
}

/**
 * Return the current time as known by the device
 */
uint64_t hwm_get_time(void)
{
	return simu_time;
}

uint64_t posix_get_hw_cycle(void)
{
	return hwm_get_time();
}

/**
 * Function to initialize the HW models
 */
void hwm_init(void)
{
	hwm_set_sig_handler();
	hwtimer_init();
	hw_counter_init();
	hw_irq_ctrl_init();

	hwm_find_next_timer();
}

/**
 * Function to free any resources allocated by the HW models
 * Note that this function needs to be designed so it is possible
 * to call it more than once during cleanup
 */
void hwm_cleanup(void)
{
	hwtimer_cleanup();
	hw_irq_ctrl_cleanup();
}
