#include "server.h"
#include "input.h"
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
#include "baseentity.h"
#include "console.h"
#include "physics.h"
#include "input.h"
#include "net.h"

void *g_serverdll;
ConVar g_tickrate("tickrate","64",FCVAR_PROTECTED);
float g_fAccumulator = 0;

extern "C" void IGame_Load(void);

//-----------------------------------------------------------------------------
// Loads game and client libraries if linking dynamically, otherwise it runs
// IGame_Load compiled statically.
//-----------------------------------------------------------------------------
void IServer::LoadGame( const char *psz )
{
#ifndef STATIC_BUILD
#ifdef __WIN32__
	g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/server.dll", psz));	
#endif
#ifdef __linux__
	g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.so", psz));	
	Plat_LoadLibrary(CUtlString("%s/bin/libclient.so", psz));

#endif
#ifdef __APPLE__
	g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.dysim", psz));	
	Plat_LoadLibrary(CUtlString("%s/bin/libclient.dysim", psz));
#endif
	void (*GameLoadfn)() = (void(*)())Plat_GetProc(g_serverdll, "IGame_Load");
	if (!GameLoadfn)
		Plat_FatalErrorFunc("IGame_Load not found in libserver.so\n");
	GameLoadfn();
#else
	IGame_Load();
#endif
};

//-----------------------------------------------------------------------------
// Updates server and client state.
//-----------------------------------------------------------------------------
void IServer::Think( float fDelta )
{
	g_fAccumulator += fDelta;
	float fTickrate = 1.0/g_tickrate.GetFloat();
	
	/* tickrate */
	while(g_fAccumulator>=fTickrate)
	{
		IInput::Frame();
		IConsole::Execute();

		g_fAccumulator-=fTickrate;
		for (auto &entity: g_entities)
		{
			entity->Think(fTickrate);
		}
		px_frame(px, fTickrate);
	}
	for (auto &entity: g_entities)
	{
		if (entity->pClientEntity)
			entity->pClientEntity->Think(fDelta);
	}
};

void IGame_Exit( int argc, char **argv ) {
	Plat_Exit(0);
}
ConCommand ExitCmd("exit", IGame_Exit, 0);
