#include "stinc.h"
#include "stmisc.h"
#include "stchat.h"
#include "stvehicle.h"
#include "stplayer.h"
#include "stveteran.h"
#include "stconsolecommands.h"

gzConsoleCommand::gzConsoleCommand()
{
	nc_ConsoleFunctionClass *c = (nc_ConsoleFunctionClass *)this;
	for (int i = 0; i < nc_ConsoleFunctionManager::FunctionList.Count(); i++)
	{
		if (nc_ConsoleFunctionManager::FunctionList[i] == c)
			return;
	}
	nc_ConsoleFunctionManager::FunctionList.Add(c);
}

#include "stnet.h"
class GetFpsConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void)
	{
		return "getfps";
	}
	char *Get_Alias()
	{
		return "gfps";
	}
	char *Get_Help(void)
	{
		return "GETFPS - Output the current server FPS.";
	}
	void Activate(char *text)
	{
		stConsole::Out("The current Server FPS is %d.\n", (gzManagerClass::m_sFps == 0) ? 1000 / *(unsigned char *)0x43BAB9 : gzManagerClass::m_sFps);

#if ISDEV()
		
		/*const char *tIps[] = {
			"202.43.220.99",
			"208.101.45.59",
			"78.129.140.5",
			"120.136.35.178",
			"66.71.244.210",
			"209.85.143.27"
		};
		for (int a = 1; a <= 1; a++)
		{
			for (int i = 0; i < sizeof(tIps) / 4; i++)
				gzPlayerTraceRoute *t = new gzPlayerTraceRoute(tIps[i]);
		}*/
		

		
		gzPlayer *gzData = gzPlayerManager::Find(1);
		if (gzData)
		{
			gzData->GetVeteran()->Promote();
		}
		

		/*
		aList<EvtNotifier> evtList;
		for (unsigned int i = 0; i < EventManager::m_list.Count(); i++)
			EventManager::m_list[i]->GetEventList(evtList, EVT_OBJECT_DAMAGE);

		stConsole::Out("Event count: %d\n", evtList.Count());
		for (aListNode<EvtNotifier> *data = evtList.GetHead(); data != NULL; data = data->GetNext())
		{
			stConsole::Out("Name: %s; Create time: %d; Type: %d; Priority: %d\n",
				data->GetData()->GetOwner()->GetName(),
				data->GetData()->GetOwner()->GetCreateTime(),
				data->GetData()->GetEventType(),
				data->GetData()->GetPriority()
			);
		}
		*/
		
#endif
	}
};
GetFpsConsoleFunction getfps;

class SetFpsConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void)
	{
		return "setfps";
	}
	char *Get_Help(void)
	{
		return "SETFPS <FPS> - Set the Server FPS.";
	}
	void Activate(char *text)
	{
		if (!*text)
			return;

		unsigned int fps = atoi(text);
		if (fps < 8 || fps > 1000) return;
		int ms = 1000 / fps;
		PatchData(&ms, 1, 0x43BAB9);
		PatchData(&ms, 1, 0x43BAC0);
		gzManagerClass::m_sFps = fps;
		stConsole::Out("Server FPS has been set to %d.\n", fps);
	}
};
SetFpsConsoleFunction setfps;

class CreateConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void)
	{
		return "create";
	}
	char *Get_Help(void)
	{
		return "CREATE <player> <preset> [amount] [side] - Spawn <amount> <preset> above <player>. (amount and side is optional, if it's not being sent, it'll be 1 and -2)";
	}
	void Activate(char *text)
	{
		if (!*text)
			return;
		aToken tok(text);
		nc_cPlayer *pData = nc_cPlayerManager::Find_Player(tok.gettok(1, ' ').ToLong());
		if (!pData)
		{
			stConsole::Out("Player #%d not found\n", tok.gettok(1, ' ').ToLong());
			return;
		}
		if (!pData->Owner.Reference)
			return;
		aTextConfig cfg("data\\NC_Stuff.ini");
		aString preset = cfg.GetData("Create_Shortcut." + tok.gettok(2, ' ').GetData(), tok.gettok(2, ' ').GetData());
		nc_DefinitionClass *objDef = nc_DefinitionMgrClass::Find_Named_Definition(preset.GetString(), true);
		if (!objDef)
		{
			stConsole::Out("Invalid preset: %s\n", preset.GetString());
			return;
		}
		int amount = 1,
			side = -2;
		if (tok.numtok(' ') >= 3)
		{
			amount = tok.gettok(3, ' ').ToLong();
			if (amount <= 0)
			{
				stConsole::Out("Invalid amount: %d\n", amount);
				return;
			}
		}
		if (tok.numtok(' ') >= 4)
		{
			side = tok.gettok(4, ' ').ToLong();
			if (side < -4 || side > 2)
			{
				stConsole::Out("Invalid side: %d\n", side);
				return;
			}
		}
		float ch = 5.0f; //create height
		if (preset.Contain("Mammoth_Tank")) ch += 1.5f;
		else if (preset.Contain("Mobile_Artillery")) ch += 0.5f;
		float facing = gzCommands->Get_Facing(pData->Owner.Reference->obj);
		nc_Vector3 pos = gzCommands->Get_Position(pData->Owner.Reference->obj);
		pos.Z += 1.0f;
		for (int i = 1; i <= amount; i++)
		{
			pos.Z += ch;
			nc_ScriptableGameObj *newObj = nc_ObjectLibraryManager::Create_Object(preset.GetString());
			gzCommands->Set_Position(newObj, pos);
			gzCommands->Set_Player_Type(newObj, side);
			gzCommands->Set_Facing(newObj, facing);
			if (newObj->As_SoldierGameObj())
				gzCommands->Attach_Script(newObj, "M00_No_Falling_Damage_DME", "");
			newObj->Start_Observers();
		}
		preset.Free_String();
	}
};
CreateConsoleFunction create;

#if ISDEV()
class AllWeaponConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void)
	{
		return "allweapon";
	}
	char *Get_Alias(void)
	{
		return "allwep";
	}
	char *Get_Help(void)
	{
		return "ALLWEAPON <player> - Give all weapons to <player>.";
	}
	void Activate(char *text)
	{
		if (!*text)
			return;
		nc_cPlayer *pData = nc_cPlayerManager::Find_Player(atoi(text));
		if (!pData || !pData->Owner.Reference)
			return;
		nc_DefinitionClass *Definition = nc_DefinitionMgrClass::Get_First(0xB001,true);
		while (Definition)
		{
			nc_WeaponDefinitionClass *WeaponDef = (nc_WeaponDefinitionClass *)Definition;
			if (WeaponDef->AGiveWeaponsWeapon)
			{
				pData->Owner.Reference->obj->As_SmartGameObj()->WeaponBag->Add_Weapon(WeaponDef,-1,true);
			}
			Definition = nc_DefinitionMgrClass::Get_Next(Definition,0xB001,true);
		}
	}
};
AllWeaponConsoleFunction allwep;

class ScriptAttachedConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void){
		return "script";
	}
	char *Get_Help(void){
		return "";
	}
	void Activate(char *text){
		if (!*text)
			return;
		nc_cPlayer *pData = nc_cPlayerManager::Find_Player(atoi(text));
		if (pData && pData->Owner.Reference)
		{
			nc_SoldierGameObj *Soldier = pData->Owner.Reference->obj->As_SoldierGameObj();
			if (Soldier->Observers.Count() > 0)
			{
				stConsole::Out("Observers count: %d\n",Soldier->Observers.Count());
				for (int i = 0; i < Soldier->Observers.Count(); i++)
					stConsole::Out("[%d] Player: %ls; Script: %s\n", i + 1, pData->PlayerName.m_Buffer, Soldier->Observers[i]->Get_Name());
			}
			else
				stConsole::Out("No observer attached to player %ls.\n", pData->PlayerName.m_Buffer);
		}
	}
};
ScriptAttachedConsoleFunction script;

class SetHealthConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void){
		return "sethealth";
	}
	char *Get_Help(void){
		return "";
	}
	void Activate(char *text){
		if (!*text)
			return;

		aToken token(text);
		nc_cPlayer *pData = nc_cPlayerManager::Find_Player(token.gettok(1, ' ').ToLong());
		if (pData)
		{
			if (pData->Owner.Reference)
			{
				pData->Owner.Reference->obj->As_DamageableGameObj()->Defense.Health = (float)token.gettok(2, ' ').ToDouble();
				pData->Owner.Reference->obj->Set_Object_Dirty_Bit(nc_DB_OCCASIONAL, true);
			}
		}
	}
};
SetHealthConsoleFunction sethealth;


class SetShieldConsoleFunction : public gzConsoleCommand {
public:
	char *Get_Name(void){
		return "setshield";
	}
	char *Get_Help(void){
		return "";
	}
	void Activate(char *text){
		if (!*text)
			return;
		aToken token(text);
		nc_cPlayer *pData = nc_cPlayerManager::Find_Player(token.gettok(1, ' ').ToLong());
		if (pData)
		{
			if (pData->Owner.Reference)
			{
				pData->Owner.Reference->obj->As_DamageableGameObj()->Defense.ShieldStrength = (float)token.gettok(2, ' ').ToDouble();
				pData->Owner.Reference->obj->Set_Object_Dirty_Bit(nc_DB_OCCASIONAL, true);
			}
		}
	}
};
SetShieldConsoleFunction setshield;
#endif
