#include <ADuCM360.h>

#include <hal/timer.h>

#include <applications/message.h>
#include <vector>
#include <ctime>
#include <cstring>
#include <cassert>

using namespace std;

vector<timer> timer_v;

#define MAX_SIZE 8

int on_tick(int argc, char *argv[])
{
	for (int i = 0; i < timer_v.size(); ++i)
	{
		if (timer_v[i].time == 0)
		{
			post_message(timer_v[i].timer_app);

			if (i != timer_v.size() - 1)
			{
				timer_v[i] = timer_v.back();
			}

			timer_v.pop_back();

			if (timer_v.capacity() - timer_v.size() > 64)
			{
				timer_v.shrink_to_fit();
			}

			--i;
		}
		else
		{
			--timer_v[i].time;
		}
	}
	return 0;
}

void new_timer(timer t)
{
	if (timer_v.size() < MAX_SIZE)
	{
		t.time /= (1000 / CLK_TCK); //time unit is ms
		timer_v.push_back(t);
	}
	else
	{
		assert(false);
	}
}

void delete_timer(const timer &t)
{
	for (int i = 0; i < timer_v.size(); ++i)
	{
		if (timer_v[i].timer_app.fun == t.timer_app.fun)
		{
			if (timer_v[i].timer_app.argc == t.timer_app.argc)
			{
				bool same = true;

				for (int j = 0; j < t.timer_app.argc; ++j) //check if all arguments same
				{
					if (strcmp(timer_v[i].timer_app.argv[j], t.timer_app.argv[j]) != 0)
					{
						same = false;
						break;
					}
				}

				if (same)
				{
					for (int k = 0; k < timer_v[i].timer_app.argc; ++k)
					{
						delete[] timer_v[i].timer_app.argv[k];
					}

					delete timer_v[i].timer_app.argv;

					if (i != timer_v.size() - 1)
					{
						timer_v[i] = timer_v.back();
					}

					timer_v.pop_back();

					if (timer_v.capacity() - timer_v.size() > 64)
					{
						timer_v.shrink_to_fit();
					}

					--i; //rescan this element
				}
			}
		}
	}
}

void update_timer(const timer &t)
{
	delete_timer(t);
	new_timer(t);
}

#ifdef __cplusplus
extern "C"
{
#endif

	void SysTick_Handler(void)
	{
		app msg;

		msg.fun = on_tick;
		msg.argc = 0;

		ts_post_message(msg);
	}

#ifdef __cplusplus
}
#endif
