#include <scgms/rtl/FilterLib.h>
#include <scgms/rtl/referencedImpl.h>
#include <scgms/utils/winapi_mapping.h>
#include <scgms/utils/string_utils.h>
#include <filters/config.h>
#include <iostream>
#include "scgms.h"

#if defined(FREERTOS)
#include <uart_print.h>
#endif

#if defined(WASM) || defined(ESP32)
void print(const char *str)
{
	printf("%s\n", str);
}
#endif

scgms::SFilter_Executor Global_Filter_Executor;

double basal_rate = 0;
const double five_minutes = 0.003;
double current_time = 0.5;
int num_of_sim_events = 0;

void create_event_sim(int event_type, double level)
{
	scgms::UDevice_Event event{scgms::NDevice_Event_Code::Level};
	current_time = current_time + five_minutes;
	event.device_time() = current_time;
	event.segment_id() = scgms::All_Segments_Id - 3;
	event.level() = level;
	switch (event_type)
	{
	case 0:
		event.signal_id() = scgms::signal_Requested_Insulin_Bolus;
		break;
	case 1:
		event.signal_id() = scgms::signal_Carb_Intake;
		break;
	case 2:
		basal_rate = level;
		break;
	default:
		break;
	}
	if (event_type < 2 && Global_Filter_Executor)
	{
		Global_Filter_Executor.Execute(std::move(event));
	}
	if (Global_Filter_Executor)
	{
		scgms::UDevice_Event event_basal{scgms::NDevice_Event_Code::Level};
		event_basal.device_time() = current_time;
		event_basal.segment_id() = scgms::All_Segments_Id - 3;
		event_basal.level() = basal_rate;
		event_basal.signal_id() = scgms::signal_Requested_Insulin_Bolus;
		Global_Filter_Executor.Execute(std::move(event_basal));
	}
}

const char *get_config_data()
{
	return config_data;
}

void create_level_event(int level_input)
{
	scgms::UDevice_Event event{scgms::NDevice_Event_Code::Level};
	event.level() = level_input;
	if (Global_Filter_Executor)
	{
		Global_Filter_Executor.Execute(std::move(event));
	}
}

void create_shutdown_event()
{
	scgms::UDevice_Event event{scgms::NDevice_Event_Code::Shut_Down};
	if (Global_Filter_Executor)
	{
		Global_Filter_Executor.Execute(std::move(event));
	}
}

int build_filter_chain(const char *configuration_input)
{
	const char *config;
	if (configuration_input == NULL)
	{
		configuration_input = config_data;
		print("Creating SCGMS filter chain from config.h");
	}
	else
	{
		print("Creating SCGMS filter chain from input");
	}
	print("------------------------------------------");
	print("Configuration:");
	print("------------------------------------------");
	refcnt::Swstr_list errors = refcnt::Swstr_list{};
	errors.get();
	scgms::SPersistent_Filter_Chain_Configuration configuration{};
	if (configuration == NULL)
	{
		print("Failed to construct SPersistent_Filter_Chain_Configuration");
		return -1;
	}

	print(configuration_input);
	print("------------------------------------------");

	print("Config errors:");
	configuration->Load_From_Memory(configuration_input, strlen(configuration_input), errors.get());
	print("------------------------------------------");

	print("Filter executor errors:");
	Global_Filter_Executor = scgms::SFilter_Executor{configuration.get(), nullptr, nullptr, errors};
	errors.for_each([](auto str)
					{auto newstr = Narrow_WString(str);print(newstr.c_str()); });
	print("------------------------------------------");

	if (Global_Filter_Executor)
	{
		print("Filter chain is ready to execute:");
		print("------------------------------------------");
	}
	else
	{
		print("Error constructing filter chain");
		print("------------------------------------------");
		return -1;
	}

	return 0;
}