#include "helper.h"
#include "runner.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "unistd.h"
#include "libgen.h"
#include "sys/stat.h"
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif

unsigned int g_hashState = 102851263;
unsigned int CProject::GenerateProjectHash( void )
{
	unsigned int hash = 5381+g_hashState;
	int c;
	char *szName = m_szName;

	while( (c = *szName++) )
		hash = (hash * 33) + c;

	g_hashState = g_hashState * 1664525 + 1013904223;

	return hash;
};

static char path[1024];
#ifdef __linux__
static ssize_t pathSize = readlink("/proc/self/exe", path, sizeof(path) - 1);
#endif
#ifdef __APPLE__
static uint32_t pathSize = sizeof(path);
int pathResult = _NSGetExecutablePath(path, &pathSize);
#endif
char *szPathDir = dirname(path);
char *szBuildDir = 0;
char *IFileSystem2::OwnDirectory()
{
	return szPathDir;
};
char *IFileSystem2::BuildDirectory()
{
	return szBuildDir;
};
	
void IFileSystem2::CopyFile( const char *szDestination, const char *szOrigin )
{
	CUtlVector<CUtlString> args = {
		CUtlString(szOrigin),
		CUtlString(szDestination),
	};
	IRunner::Run("cp", args);
}
void IFileSystem2::CopyDirectory( const char *szDestination, const char *szOrigin )
{
	CUtlVector<CUtlString> args = {
		"-r",
		CUtlString(szOrigin),
		CUtlString(szDestination),
	};
	IRunner::Run("cp", args);
}

void IFileSystem2::MakeDirectory( const char *psz )
{
	CUtlVector<CUtlString> args = {
		"-p",
		CUtlString(psz),
	};
	IRunner::Run("mkdir", args);
};

bool IFileSystem2::ShouldRecompile(const char *szSource, const char *szOutput)
{
	struct stat srcbuf;
	struct stat outbuf;
	if (stat(szSource, &srcbuf) != 0) {
		return true;
	}
	if (stat(szOutput, &outbuf) != 0) {
		return true;
	}
	return outbuf.st_mtime < srcbuf.st_mtime;
};

CUtlVector<CBuildStage*> g_buildStages;

CBuildStage::CBuildStage( CUtlString sz, int(*pMainFn)() )
{
	m_sz = sz;
	m_pMainFn = pMainFn;
	if (sz == 0 || pMainFn == 0)
		Plat_FatalErrorFunc("Name and function pointer must be set\n");
	
	g_buildStages.AppendTail(this);
};

CUtlVector<CBuildStage*>& BuildStages()
{
	return g_buildStages;
}
