
#include "MainLoop.h"
#include <stdio.h>

// Live++ API
#include "LivePP/API/x64/LPP_API_x64_CPP.h"

// Live++: these functions demonstrate pre-compile and post-compile hooks
static void FunctionCalledOnPreCompile(lpp::LppPrecompileHookId, const wchar_t* const recompiledModulePath, unsigned int filesToCompileCount)
{
	printf("Precompile: %S, %u file(s)\n", recompiledModulePath, filesToCompileCount);
}

static void FunctionCalledOnPostCompile(lpp::LppPostcompileHookId, const wchar_t* const recompiledModulePath, unsigned int filesToCompileCount)
{
	printf("Postcompile: %S, %u file(s)\n", recompiledModulePath, filesToCompileCount);
}

LPP_PRECOMPILE_HOOK(FunctionCalledOnPreCompile);
LPP_POSTCOMPILE_HOOK(FunctionCalledOnPostCompile);


// Live++: these functions demonstrate compile hooks
static void FunctionCalledOnCompileStart(lpp::LppCompileStartHookId, const wchar_t* const recompiledModulePath, const wchar_t* const recompiledSourcePath)
{
	printf("CompileStart: %S, %S\n", recompiledModulePath, recompiledSourcePath);
}

static void FunctionCalledOnCompileSuccess(lpp::LppCompileSuccessHookId, const wchar_t* const recompiledModulePath, const wchar_t* const recompiledSourcePath)
{
	printf("CompileSuccess: %S, %S\n", recompiledModulePath, recompiledSourcePath);
}

static void FunctionCalledOnCompileError(lpp::LppCompileErrorHookId, const wchar_t* const recompiledModulePath, const wchar_t* const recompiledSourcePath, const wchar_t* const compilerOutput)
{
	printf("CompileError: %S, %S\n%S\n", recompiledModulePath, recompiledSourcePath, compilerOutput);
}

LPP_COMPILE_START_HOOK(FunctionCalledOnCompileStart);
LPP_COMPILE_SUCCESS_HOOK(FunctionCalledOnCompileSuccess);
LPP_COMPILE_ERROR_HOOK(FunctionCalledOnCompileError);


// Live++: these functions demonstrate link hooks
static void FunctionCalledOnLinkStart(lpp::LppLinkStartHookId, const wchar_t* const recompiledModulePath)
{
	printf("LinkStart: %S\n", recompiledModulePath);
}

static void FunctionCalledOnLinkSuccess(lpp::LppLinkSuccessHookId, const wchar_t* const recompiledModulePath)
{
	printf("LinkSuccess: %S\n", recompiledModulePath);
}

static void FunctionCalledOnLinkError(lpp::LppLinkErrorHookId, const wchar_t* const recompiledModulePath, const wchar_t* const linkerOutput)
{
	printf("LinkError: %S\n%S\n", recompiledModulePath, linkerOutput);
}

LPP_LINK_START_HOOK(FunctionCalledOnLinkStart);
LPP_LINK_SUCCESS_HOOK(FunctionCalledOnLinkSuccess);
LPP_LINK_ERROR_HOOK(FunctionCalledOnLinkError);


// Live++: these functions demonstrate global hooks
static void FunctionCalledOnHotReloadStart(lpp::LppGlobalHotReloadStartHookId)
{
	printf("Hot-Reload start\n");
}

static void FunctionCalledOnHotReloadEnd(lpp::LppGlobalHotReloadEndHookId)
{
	printf("Hot-Reload end\n");
}

LPP_GLOBAL_HOTRELOAD_START_HOOK(FunctionCalledOnHotReloadStart);
LPP_GLOBAL_HOTRELOAD_END_HOOK(FunctionCalledOnHotReloadEnd);


// main entry point
int main(void)
{
	// create a synchronized Live++ agent
	lpp::LppSynchronizedAgent lppAgent = lpp::LppCreateSynchronizedAgent(nullptr, L"../../../LivePP");
	if (!lpp::LppIsValidSynchronizedAgent(&lppAgent))
	{
		return 1;
	}

	lppAgent.EnableModule(lpp::LppGetCurrentModulePath(), lpp::LPP_MODULES_OPTION_NONE, nullptr, nullptr);

	// init the example
	MainLoop::Init("Example 06: Hooks");
	MainLoop::Announce(lppAgent, "../../readme/README_Hooks.txt");

	while (MainLoop::PollInput(lppAgent))
	{
		// listen to hot-reload and hot-restart requests
		if (lppAgent.WantsReload(lpp::LPP_RELOAD_OPTION_SYNCHRONIZE_WITH_RELOAD))
		{
			// Live++: client code can do whatever it wants here, e.g. synchronize across several threads, the network, etc.
			lppAgent.Reload(lpp::LPP_RELOAD_BEHAVIOUR_WAIT_UNTIL_CHANGES_ARE_APPLIED);
		}

		if (lppAgent.WantsRestart())
		{
			// Live++: client code can do whatever it wants here, e.g. finish logging, abandon threads, etc.
			lppAgent.Restart(lpp::LPP_RESTART_BEHAVIOUR_INSTANT_TERMINATION, 0u, nullptr);
		}

		// run the main loop
		MainLoop::Update();
		MainLoop::Render();
		MainLoop::Present();
	}

	MainLoop::Exit();

	lpp::LppDestroySynchronizedAgent(&lppAgent);

	return 0;
}
