// Fill out your copyright notice in the Description page of Project Settings.


#include "Log/CsdkLogSingleton.h"

#include "Entity/Remote/CsdkTraceOutputRemote.h"
#include "Log/Entity/CsdkTrace.h"
#include "Log/Entity/Local/CsdkTraceOutputFile.h"
#include "Output/Remote/LogForwarder.h"


#define GROWABLE_LOGF(SerializeFunc) \
int32	BufferSize	= 1024; \
TCHAR*	Buffer		= NULL; \
int32	Result		= -1; \
/* allocate some stack space to use on the first pass, which matches most strings */ \
TCHAR	StackBuffer[512]; \
TCHAR*	AllocatedBuffer = NULL; \
\
/* first, try using the stack buffer */ \
Buffer = StackBuffer; \
GET_VARARGS_RESULT( Buffer, UE_ARRAY_COUNT(StackBuffer), UE_ARRAY_COUNT(StackBuffer) - 1, Fmt, Fmt, Result ); \
\
/* if that fails, then use heap allocation to make enough space */ \
while(Result == -1) \
{ \
FMemory::SystemFree(AllocatedBuffer); \
/* We need to use malloc here directly as GMalloc might not be safe. */ \
Buffer = AllocatedBuffer = (TCHAR*) FMemory::SystemMalloc( BufferSize * sizeof(TCHAR) ); \
if (Buffer == NULL) \
{ \
return; \
} \
GET_VARARGS_RESULT( Buffer, BufferSize, BufferSize-1, Fmt, Fmt, Result ); \
BufferSize *= 2; \
}; \
Buffer[Result] = 0; \
; \
\
SerializeFunc; \
FMemory::SystemFree(AllocatedBuffer);

CsdkLogSingleton::CsdkLogSingleton()
{
	LogTracer = MakeShareable(new CsdkTrace);
	LogTracer->SetTraceLevel(ELogVerbosity::All);
	LogTracer->AddOutput(MakeShareable(new CsdkTraceOutputFile));
	if (!UE_BUILD_SHIPPING)
		LogTracer->AddOutput(MakeShareable(new CsdkTraceOutputRemote));
}

CsdkLogSingleton& CsdkLogSingleton::GetInst()
{
	static CsdkLogSingleton Singleton;
	return Singleton;
}

void CsdkLogSingleton::LogfImpl( const FName& Category,
                                 ELogVerbosity::Type Verbosity, const TCHAR* Fmt, ...) const
{
	GROWABLE_LOGF(LogTracer->Log(Category, Verbosity, Buffer))
}
