#include "timer_dev.h"

#include "Events.h"



// MONITOR_TIME.addwatch(pRuntime, onbegin, callback_parameters, MONITOR_FLAG_NONE, EVENT_TIMER_P(e)->begin, 0, 0);
void* timer_addwatch(PRUNTIME pRuntime, void* (*callback)(void *), void *args, int flags, ...)
{
	PVARIABLES_EVENTS pVariables = (PVARIABLES_EVENTS)(pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpVariables);
	PSTRINGS_EVENTS pStrings = (PSTRINGS_EVENTS)(pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpStrings);

	API_ENTERCRITICALSECTION(&pVariables->pTimerCriticalSection);

	PMONITORED_TIMER_ENTRY timer = (PMONITORED_TIMER_ENTRY)API_ALLOC(pRuntime, sizeof(MONITORED_TIMER_ENTRY));

	timer->callback = callback;
	timer->args = args;
	timer->flags = flags;
	timer->keyPtr = API_ALLOC(pRuntime, sizeof(VOID*));

	

	va_list va;
	va_start(va, flags);
	timer->time = va_arg(va, int);
	
	if ((timer->delay = va_arg(va, int)) < 1) 
		timer->delay = 1;
	
	if ((timer->iter = va_arg(va, int)) < 0)
		timer->iter = 0;

	va_end(va);

	HASH_ADD_PTR(pRuntime, pVariables->pMonitoredTimerList, keyPtr, timer);

	API_LEAVECRITICALSECTION(&pVariables->pTimerCriticalSection);

	OUTPUTDEBUG("[*] Timer: time %d delay %d iter %d\n", timer->time, timer->delay, timer->iter);

	return timer;


}

void* timer_delwatch(PRUNTIME pRuntime, void *entry)
{
	PVARIABLES_EVENTS pVariables = (PVARIABLES_EVENTS)(pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpVariables);
	PSTRINGS_EVENTS pStrings = (PSTRINGS_EVENTS)(pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpStrings);
	
	API_ENTERCRITICALSECTION(&pVariables->pTimerCriticalSection);



	PMONITORED_TIMER_ENTRY tmpTimer, timer = (PMONITORED_TIMER_ENTRY)entry;

	HASH_FIND_PTR(pRuntime, pVariables->pMonitoredTimerList, &timer->keyPtr, tmpTimer);

	if (tmpTimer != NULL)
	{
		HASH_DEL(pRuntime, pVariables->pMonitoredTimerList, timer);

		// TODO: fix leak
		API_FREE(pRuntime, timer);
	}
	else
		DebugBreak();

	
	API_LEAVECRITICALSECTION(&pVariables->pTimerCriticalSection);

	return NULL;
}

void monitor_timer_start(PRUNTIME pRuntime)
{

	PVARIABLES_EVENTS pVariablesevent = pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpVariables;

	pVariablesevent->pMonitoredTimerList = NULL;
	API_INITIALIZECRITICALSECTION(&pVariablesevent->pTimerCriticalSection);
}