#include <UnitTest++.h>

#include "Logging.h"
#include "Module.h"
#include "EventManager.h"

using namespace std;
using namespace Engine;

int global_event_type = -1;
string global_event_string = "";

struct EventsFixture;

class TestEventModule : public Module {
	private:
		virtual int OnInit (int argc, char* argv[]) {
			return 0;
		};
	virtual bool OnReceiveEvent (const EventBasePtr &event) {
			global_event_type = event->mEventType;
			global_event_string = event->mEventData;

			return true;
	}

	friend class EventsFixture;
};

struct EventsFixture {
	EventsFixture () {
		LoggingModule.Init (0, NULL);
		LoggingModule.SetLogPrintLevel (LogLevelWarning);

		TestEventManager = new EventManager;

		global_event_type = -1;
		global_event_string = "";
	}

	~EventsFixture () {
		delete TestEventManager;
		TestEventManager = NULL;

		LoggingModule.Destroy ();
	}

	Logging LoggingModule;

	TestEventModule TestModule;
	EventManager *TestEventManager;
};

TEST_FIXTURE ( EventsFixture, TestEventModuleSendEvent ) {
	EventBasePtr event (new EventBase);

	event->mEventType = 1;
	event->mEventData = "test";

	TestModule.SendEvent (event);

	CHECK_EQUAL (1, global_event_type);
	CHECK_EQUAL ("test", global_event_string);
}

TEST_FIXTURE ( EventsFixture, TestTestEventManagerZeroListeners ) {
	CHECK_EQUAL (false, TestEventManager->HasEventTypeListener(123));
	CHECK_EQUAL (0, TestEventManager->GetEventTypeListenerCount(123));
}

TEST_FIXTURE ( EventsFixture, TestTestEventManagerAddListener ) {
	TestEventManager->RegisterListener (&TestModule, 1);

	CHECK_EQUAL (true, TestEventManager->HasEventTypeListener(1));
	CHECK_EQUAL (false, TestEventManager->HasEventTypeListener(2));

	TestEventManager->RegisterListener (&TestModule, 1);
	CHECK_EQUAL (2, TestEventManager->GetEventTypeListenerCount(1));
}

TEST_FIXTURE ( EventsFixture, TestTestEventManagerTriggerEvent ) {
	TestEventManager->RegisterListener (&TestModule, 1);

	CHECK_EQUAL (true, TestEventManager->HasEventTypeListener(1));

	EventBasePtr event (new EventBase);

	event->mEventType = 1;
	event->mEventData = "test";

	CHECK_EQUAL (true, TestEventManager->TriggerEvent (event));

	CHECK_EQUAL (1, global_event_type);
	CHECK_EQUAL ("test", global_event_string);

	event->mEventType = 0;
	CHECK_EQUAL (false, TestEventManager->TriggerEvent (event));
}

TEST_FIXTURE ( EventsFixture, TestTestEventManagerQueueEvent ) {
	TestEventManager->RegisterListener (&TestModule, 1);

	EventBasePtr event (new EventBase);

	event->mEventType = 1;
	event->mEventData = "test";

	CHECK_EQUAL (true, TestEventManager->QueueEvent (event));
	CHECK_EQUAL (1, TestEventManager->GetQueuedEventCount());
	CHECK_EQUAL (true, TestEventManager->QueueEvent (event));
	CHECK_EQUAL (2, TestEventManager->GetQueuedEventCount());

	event->mEventType = 2;
	CHECK_EQUAL (false, TestEventManager->QueueEvent (event));
}

TEST_FIXTURE ( EventsFixture, TestTestEventManagerProcess ) {
	TestEventManager->RegisterListener (&TestModule, 1);

	EventBasePtr event (new EventBase);

	event->mEventType = 1;
	event->mEventData = "test";

	CHECK_EQUAL (true, TestEventManager->QueueEvent (event));
	CHECK_EQUAL (1, TestEventManager->GetQueuedEventCount());
	CHECK_EQUAL (true, TestEventManager->QueueEvent (event));
	CHECK_EQUAL (2, TestEventManager->GetQueuedEventCount());

	TestEventManager->Process();
	CHECK_EQUAL (1, global_event_type);
	CHECK_EQUAL ("test", global_event_string);
	CHECK_EQUAL (0, TestEventManager->GetQueuedEventCount());
}
