#include <ADuCM360.h>
#include <applications/message.h>

#include <list>
#include <cassert>

using namespace std;

list<app> msg_l;

#define MAX_SIZE 32

//ts: thread safe
#define TS_BUF_LEN 16
static struct app ts_msg_buf[TS_BUF_LEN];
static volatile int ts_msg_front = 0, ts_msg_back = 0;

void ts_post_message(struct app &msg)
{
	assert(ts_msg_back != (ts_msg_front - 1));
	assert(!(ts_msg_back == (TS_BUF_LEN - 1) && ts_msg_front == 0));
	assert(msg.argc == 0); // new and delete parameter is not thread safe

	ts_msg_buf[ts_msg_back] = msg;

	if (ts_msg_back == TS_BUF_LEN - 1)
	{
		ts_msg_back = 0;
	}
	else
	{
		++ts_msg_back;
	}
}

void post_message(struct app &msg)
{
	if (msg_l.size() < MAX_SIZE)
	{
		msg_l.push_back(msg);
	}
	else
	{
		assert(false);
	}
}

void execute(struct app application)
{
	(*application.fun)(application.argc, application.argv);

	for (int i = 0; i < application.argc; ++i)
	{
		delete[] application.argv[i];
	}

	delete application.argv;
}

void message_loop(void)
{
	while (ts_msg_front != ts_msg_back)
	{
		ts_msg_buf[ts_msg_front].argv = new char*; //ts_post_message not thread safe for new

		post_message(ts_msg_buf[ts_msg_front]);

		if (ts_msg_front == TS_BUF_LEN - 1)
		{
			ts_msg_front = 0;
		}
		else
		{
			++ts_msg_front;
		}
	}

	if (!msg_l.empty())
	{
		execute(msg_l.front());

		msg_l.pop_front();
	}
}
