#include "YaRRIncludes.h"


/************************************** Polite Request ***************************************
** I have put a lot of time and effort into YaRR. If you want to use some of the source     **
** please tell me. Anything used from YaRR must be open source, as is scripts.dll.          **
***************************************** Thank you *****************************************/


Stacker<Task *> *YaRRWorker::Tasks = 0;
CRITICAL_SECTION YaRRWorker::Mutex;
void *YaRRWorker::WorkerObj = 0;

DWORD __stdcall YaRRWorker::Worker(void *)
{
	while(1)
	{
		if(Tasks)
		{
			EnterCriticalSection(&Mutex);
			Task *const*t__ = Tasks->At(0);
			if(t__)
			{
				Task *t_ = *t__;
				if(t_->Count-- >= 1)
				{
					if(strcmp(t_->Name, "CALL") == 0)
					{
						unsigned int ret = t_->CALL(t_->Param);
						if(ret != 0)			
						{						
							t_->Count = ret;
							Tasks->Push(t_);
						}
						else
						{
							if(t_->Param)
							{	
								CDealloc(t_->Param);
							}
							CDealloc(t_);
						}
					}
					Tasks->Erase(0);
				}
				
			}
			Sleep(0);
			LeaveCriticalSection(&Mutex);
		}
		Sleep(1);
	}
	return 0;
}

void YaRRWorker::Addtask(Task &t_)
{
	DLOG;
	EnterCriticalSection(&Mutex);
	Task *t = Alloc(Task);
	*t = t_;
	Tasks->Push(t);
	LeaveCriticalSection(&Mutex);
}

void YaRRWorker::Startup()
{
	DLOG;
	InitializeCriticalSection(&Mutex);
	Tasks = Alloc(Stacker<Task *>);
	if(!WorkerObj)
	{
		WorkerObj = CreateThread(NULL, NULL, Worker, NULL, NULL, NULL);
	}
	
	
}

void YaRRWorker::Shutdown()
{
	DLOG;
	if(!Tasks)
	{
		return;
	}
	EnterCriticalSection(&Mutex);

	IterateStack(x, Task *, Tasks)
	{

		if(x->Param)
		{	
			CDealloc(x->Param);
		}
		CDealloc(x);
	}

	if(WorkerObj)
	{
		TerminateThread(WorkerObj, 0);
		CloseHandle(WorkerObj);
	}
	WorkerObj = 0;
	LeaveCriticalSection(&Mutex);
	DeleteCriticalSection(&Mutex);

	Dealloc(Stacker<Task *>, Tasks);
	Tasks = 0;
}

char YaRRWorker::Flags()
{
	DLOG;
	char ret = 0;
	if(WorkerObj)
	{
		ret |= WORKER_RUNNING;
	}
	else
	{
		return 0;
	}

	if(Tasks->Length() == 0)
	{
		ret |= WORKER_IDLE;
	}
	else
	{
		ret |= WORKER_BUSY;
	}
	LeaveCriticalSection(&Mutex);
	return ret;
}