#define LOG_ENABLED
#include "utilities/Log.h"
#include "unittest/TestSuite.h"

struct logWriteContext {
	unsigned int callCount;
	int level;
	const char * file;
	const char * function;
	unsigned int line;
	const char * format;
	unsigned int argCount;
	int args[2];
};

static void testWriteCallback(int level, const char * file, const char * function, unsigned int line, const char * format, va_list args, void * context) {
	struct logWriteContext * contextStruct = context;
	contextStruct->callCount++;
	contextStruct->level = level;
	contextStruct->file = file;
	contextStruct->function = function;
	contextStruct->line = line;
	contextStruct->format = format;
	for (unsigned int argIndex = 0; argIndex < contextStruct->argCount; argIndex++) {
		contextStruct->args[argIndex] = va_arg(args, int);
	}
}

static void testLogWrite(void) {
	struct logWriteContext contextStruct = {.callCount = 0, .level = 0, .file = NULL, .function = NULL, .line = 0, .format = NULL};
	Log_setWriteCallback(testWriteCallback, &contextStruct);
	
	contextStruct.argCount = 2;
	Log_write(1, "a", "b", 2, "%d%d", 3, 4);
	TestCase_assertUIntEqual(contextStruct.callCount, 1);
	TestCase_assertIntEqual(contextStruct.level, 1);
	TestCase_assertStringEqual(contextStruct.file, "a");
	TestCase_assertStringEqual(contextStruct.function, "b");
	TestCase_assertUIntEqual(contextStruct.line, 2);
	TestCase_assertStringEqual(contextStruct.format, "%d%d");
	TestCase_assertIntEqual(contextStruct.args[0], 3);
	TestCase_assertIntEqual(contextStruct.args[1], 4);
	
	contextStruct.argCount = 1;
	Log_write(4, "c", "d", 5, "%d", 6);
	TestCase_assertUIntEqual(contextStruct.callCount, 2);
	TestCase_assertIntEqual(contextStruct.level, 4);
	TestCase_assertStringEqual(contextStruct.file, "c");
	TestCase_assertStringEqual(contextStruct.function, "d");
	TestCase_assertUIntEqual(contextStruct.line, 5);
	TestCase_assertStringEqual(contextStruct.format, "%d");
	TestCase_assertIntEqual(contextStruct.args[0], 6);
	
	contextStruct.argCount = 0;
	LOG(9, "hi"); unsigned int logLine = __LINE__;
	TestCase_assertUIntEqual(contextStruct.callCount, 3);
	TestCase_assertIntEqual(contextStruct.level, 9);
	TestCase_assertStringEqual(contextStruct.file, __FILE__);
	TestCase_assertStringEqual(contextStruct.function, __FUNCTION__);
	TestCase_assertUIntEqual(contextStruct.line, logLine);
	TestCase_assertStringEqual(contextStruct.format, "hi");
}

TEST_SUITE(LogTest,
           testLogWrite)
