#include "public/c.h"
#include "public/helper.h"
#include "public/ld.h"
#include "public/target.h"
#include "tier0/platform.h"
#include "tier1/commandline.h"
#include "c.h"
#include "tier1/utlvector.h"
#include "signal.h"
#include "libgen.h"
#include <unistd.h>

CUtlString owndir;
int build()
{

	extern char *szBuildDir;

	CCProject compileScriptProject = {};
	compileScriptProject.m_szName = "build";
	compileScriptProject.files = {"build.cpp"};
	compileScriptProject.includeDirectories = {CUtlString("%s/public",IFileSystem2::OwnDirectory()),CUtlString("%s/public", IFileSystem2::BuildDirectory()), CUtlString("%s/../public",IFileSystem2::OwnDirectory()),CUtlString("%s/../public", IFileSystem2::BuildDirectory())};
	compileScriptProject.bFPIC = true;
	compileScriptProject.m_target = Target_t::HostTarget();
	CLDProject linkScriptProject = compileScriptProject.Compile();
	linkScriptProject.linkType = ELINK_DYNAMIC_LIBRARY;
	linkScriptProject.m_target = Target_t::HostTarget();
	CUtlString script = linkScriptProject.Link();
	void *scriptDLL = Plat_LoadLibrary(script);

	auto PreinitFn = (void(*)())Plat_GetProc(scriptDLL, "Preinit");
	V_printf("%p\n",PreinitFn);
	if (PreinitFn)
		PreinitFn();

	for (auto &build: BuildStages())
	{
		build->m_pMainFn();
	};
	Plat_UnloadLibrary(scriptDLL);
	CCProject::GenerateCompileCommands();

	return 0;
};
void IEngine_Signal(int sig)
{
	switch (sig)
	{
	case SIGSEGV:
	case SIGILL:
	case SIGABRT:
		Plat_Backtrace();
		Plat_FatalErrorFunc("Fault");
		break;
	default:
		break;
	};
	Plat_Exit(0);
};

int main(int c, char **v)
{	
	char path[1024];

	CUtlString buildcppDir = getcwd(path, 1024);
	owndir = buildcppDir;
	char *szBuildcppDir = buildcppDir.GetString();
findbuild:
	FILE* file = V_fopen("build.cpp", "rb");
	if (!file)
	{
		dirname(szBuildcppDir);
		if (buildcppDir=="/")
		{
			V_printf("build.cpp not found\n");
			return 0;
		}
		chdir(szBuildcppDir);
		goto findbuild;
	} else {
		V_fclose(file);
	}
	extern char *szBuildDir;
	szBuildDir = szBuildcppDir;

	#ifdef __linux
	signal(SIGHUP, IEngine_Signal);
	signal(SIGINT, IEngine_Signal);
	signal(SIGQUIT, IEngine_Signal);
	signal(SIGILL, IEngine_Signal);
	signal(SIGTRAP, IEngine_Signal);
	signal(SIGIOT, IEngine_Signal);
	signal(SIGBUS, IEngine_Signal);
	signal(SIGFPE, IEngine_Signal);
	signal(SIGSEGV, IEngine_Signal);
	signal(SIGTERM, IEngine_Signal);
	#endif
	ICommandLine::CreateCommandLine(c, v);
	if (ICommandLine::CheckParam("build"))
		return build();
	return 0;
};
