#include ".\pythoninclude\Python.h"
#include "scripts.h"
#include "engine.h"
#include "helper_functions.h"
#include "jnz_hooks.h"

PyObject* scriptsdll_randombuilding(PyObject *self, PyObject *args)
{
	GameObject *obj;
	int id;

	obj = Find_Building(Helper::Random_Int(2), Helper::Random_Int(9));
	while(!obj)
	{
		obj = Find_Building(Helper::Random_Int(2), Helper::Random_Int(9));
	}

	id = Helper::Get_ID(obj);
	return Py_BuildValue("i", id);
}

PyObject* scriptsdll_getcurrentmap(PyObject *self, PyObject *args)
{
	const char* map;

	map = The_Game()->MapName;
	return Py_BuildValue("s", map);
}

PyObject* scriptsdll_getnextmap(PyObject *self, PyObject *args)
{
	const char* map;

	map = The_Game()->MapList[The_Game()->MapNumber+1] == 0 ? The_Game()->MapList[0] : The_Game()->MapList[The_Game()->MapNumber+1];
	return Py_BuildValue("s", map);
}

PyCFunction* scriptsdll_applydamage(PyObject *self, PyObject *args)
{
	int whoid, damagerid;
	float amount;
	const char* type;

	damagerid = 0;

	if (!PyArg_ParseTuple(args, "ifs|i", &whoid, &amount, &type, &damagerid))
	{
		printf("\nError occured inside scriptsdll.applydamage.\n Bad argument(s)?\n");
        return NULL;
	}
	Commands->Apply_Damage(Commands->Find_Object(whoid), amount, type, damagerid ? Commands->Find_Object(damagerid): 0);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}


PyObject* scriptsdll_getfacing(PyObject *self, PyObject *args)
{
	int id;
	float facing;

	if (!PyArg_ParseTuple(args, "i", &id))
	{
		printf("\nError occured inside scriptsdll.getfacing.\n Bad argument(s)?\n");
        return NULL;
	}
	facing = Commands->Get_Facing(Commands->Find_Object(id));
	return Py_BuildValue("f", facing);
}

PyCFunction* scriptsdll_setfacing(PyObject *self, PyObject *args)
{
	int id;
	float facing;

	if (!PyArg_ParseTuple(args, "if", &id, &facing))
	{
		printf("\nError occured inside scriptsdll.setfacing.\n Bad argument(s)?\n");
        return NULL;
	}
	Commands->Set_Facing(Commands->Find_Object(id), facing);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_setclouds(PyObject *self, PyObject *args)
{
	float cover, gloominess, transition;

	if (!PyArg_ParseTuple(args, "fff", &cover, &gloominess, &transition))
	{
		printf("\nError occured inside scriptsdll.setclouds.\n Bad argument(s)?\n");
        return NULL;
	}
	Commands->Set_Clouds(cover, gloominess, transition);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_setash(PyObject *self, PyObject *args)
{
	float density, transition;
	int unused;

	if (!PyArg_ParseTuple(args, "ffi", &density, &transition, &unused))
	{
		printf("\nError occured inside scriptsdll.setash.\n Bad argument(s)?\n");
        return NULL;
	}
	bool enable = (unused > 0 ? 1 : 0);

	Commands->Set_Ash(density, transition, enable);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_setrain(PyObject *self, PyObject *args)
{
	float density, transition;
	int unused;

	if (!PyArg_ParseTuple(args, "ffi", &density, &transition, &unused))
	{
		printf("\nError occured inside scriptsdll.setrain.\n Bad argument(s)?\n");
        return NULL;
	}
	bool enable = (unused > 0 ? 1 : 0);

	Commands->Set_Rain(density, transition, enable);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_setsnow(PyObject *self, PyObject *args)
{
	float density, transition;
	int unused;

	if (!PyArg_ParseTuple(args, "ffi", &density, &transition, &unused))
	{
		printf("\nError occured inside scriptsdll.setsnow.\n Bad argument(s)?\n");
        return NULL;
	}
	bool enable = (unused > 0 ? 1 : 0);

	Commands->Set_Snow(density, transition, enable);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_attachscript(PyObject *self, PyObject *args)
{
	const char *script, *params;
	int id;

	if (!PyArg_ParseTuple(args, "iss", &id, &script, &params))
	{
		printf("\nError occured inside scriptsdll.attachscript.\n Bad argument(s)?\n");
        return NULL;
	}

	Commands->Attach_Script(Commands->Find_Object(id), script, params);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyObject* scriptsdll_createobjectatbone(PyObject *self, PyObject *args)
{
	int id, createdid;
	const char *preset, *bone;

	if (!PyArg_ParseTuple(args, "iss", &id, &preset, &bone))
	{
		printf("\nError occured inside scriptsdll.createobjectatbone.\n Bad argument(s)?\n");
        return NULL;
	}
	createdid = Helper::Get_ID(Commands->Create_Object_At_Bone(Commands->Find_Object(id), preset, bone));
	return Py_BuildValue("i", createdid);
}

PyCFunction* scriptsdll_attachtoobjectbone(PyObject *self, PyObject *args)
{
	const char *bone;
	int attachid, boneid;

	if (!PyArg_ParseTuple(args, "iis", &attachid, &boneid, &bone))
	{
		printf("\nError occured inside scriptsdll.attachtoobjectbone.\n Bad argument(s)?\n");
        return NULL;
	}

	Commands->Attach_To_Object_Bone(Commands->Find_Object(attachid), Commands->Find_Object(boneid), bone);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyCFunction* scriptsdll_displayhealthbar(PyObject *self, PyObject *args)
{
	int id, enable;
	

	if (!PyArg_ParseTuple(args, "ii", &id, &enable))
	{
		printf("\nError occured inside scriptsdll.displayhealthbar.\n Bad argument(s)?\n");
        return NULL;
	}

	bool benable = (enable > 0 ? 1 : 0);
	Commands->Display_Health_Bar(Commands->Find_Object(id), benable);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyObject* scriptsdll_createscriptzone(PyObject *self, PyObject *args)
{
	int id;
	const char *preset;
	float posx, posy, posz;
	float extentx, extenty, extentz;

	if (!PyArg_ParseTuple(args, "sffffff", &preset, &posx, &posy, &posz, &extentx, &extenty, &extentz))
	{
		printf("\nError occured inside scriptsdll.createscriptzone.\n Bad argument(s)?\n");
        return NULL;
	}
	
	Vector3 position, extent;
	position = Vector3(posx, posy, posz);
	extent = Vector3(extentx, extenty, extentz);

	OBBoxClass box;
	memset((void *)&box.Basis, 0, 3*3);
	box.Basis[0][0] = 1.0f;
	box.Basis[1][1] = 1.0f;
	box.Center = position;
	box.Extent = extent;

	id = Helper::Get_ID(Create_Zone(preset, box));
	return Py_BuildValue("i", id);
}

PyCFunction* scriptsdll_requestserial(PyObject *self, PyObject *args)
{
	int id;

	if (!PyArg_ParseTuple(args, "i", &id))
	{
		printf("\nError occured inside scriptsdll.Request_Serial.\n Bad argument(s)?\n");
        return NULL;
	}

	StringClass tmp;
	RequestSerial(id, tmp);
	Py_INCREF(Py_None);
	return (PyCFunction*)Py_None;
}

PyObject* scriptsdll_cplayer(PyObject *self, PyObject *args)
{
	int playerid;

	if (!PyArg_ParseTuple(args, "i", &playerid))
	{
		printf("\nError occured inside scriptsdll.cPlayer.\n Bad argument(s)?\n");
        return NULL;
	}

	cPlayer *p = 0;
	for(GenericSLNode *x = PlayerList->HeadNode; x; x = x->NodeNext)
	{
		if(((cPlayer *)x->NodeData)->PlayerId == playerid)
		{
			p = (cPlayer *)x->NodeData;
			break;
		}
	}

	if(p)
	{
		char playername[256];
		sprintf(playername, "%S", (const wchar_t *)p->PlayerName);

						// Doesn't this look nice?
		return Py_BuildValue("{s:i,s:i,s:i,s:i,s:I,s:I,s:f,s:i,s:i,s:i,s:i,s:i,s:f,s:i,s:f,s:i,s:i,s:l,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:I,s:I,s:i,s:i,s:f,s:i,s:i,s:s,s:i,s:i,s:i,s:f,s:f,s:i,s:i,s:i,s:i,s:i,s:i,s:f}",  //45
			"AlliesKilled", p->AlliesKilled, //1
			"ArmHit", p->ArmHit, //2
			"ArmShots", p->ArmShots, //3
			"BuildingDestroyed", p->BuildingDestroyed, //4
			"ClientUpdateFrequency", p->ClientUpdateFrequency, //5
			"CreationTime", p->CreationTime, //6
			"CreditGrant", p->CreditGrant, //7
			"CrotchHit", p->CrotchHit, //8
			"CrotchShots", p->CrotchShots,	//9
			"DamageScaleFactor", p->DamageScaleFactor, //10
			"Deaths", p->Deaths.Get(), //11
			"EnemiesKilled", p->EnemiesKilled, //12
			"FinalHealth", p->FinalHealth, //13
			"Fps", p->Fps, //14
			"GameTime", p->GameTime, //15
			"HeadHit", p->HeadHit, //16
			"HeadShots", p->HeadShots, //17
			"IpAddress", (long)p->IpAddress, //18
			"IsActive", p->IsActive, //19
			"IsHuman", p->IsHuman, //20
			"IsInGame", p->IsInGame, //21
			"IsWaitingForIntermission", p->IsWaitingForIntermission, //22
			"JoinTime", p->JoinTime, //23
			"Kills", p->Kills.Get(), //24
			"KillsFromVehicle", p->KillsFromVehicle, //25
			"LastDamaged", p->LastDamaged, //26
			"LastDamager", p->LastDamager, //27
			"LegHit", p->LegHit, //28
			"LegShots", p->LegShots, //29
			"Money", p->Money.Get(), //30
			"Ping", p->Ping, //31
			"PlayerId", p->PlayerId, //32
			"Playername", playername, //33
			"PlayerType", p->PlayerType.Get(), //34
			"PowerupsCollected", p->PowerupsCollected, //35
			"Rung", p->Rung.Get(), //36
			"Score", p->Score.Get(), //37
			"SessionTime", p->SessionTime, //38
			"ShotsFired", p->ShotsFired, //39
			"Squishes", p->Squishes, //40
			"TorsoHit", p->TorsoHit, //41
			"TorsoShots", p->TorsoShots, //42
			"TotalTime", p->TotalTime, //43
			"VehiclesDestroyed", p->VehiclesDestroyed, //44
			"VehicleTime", p->VehicleTime); //45 */
	}
	return NULL;
}

PyObject* scriptsdll_thegame(PyObject *self, PyObject *args)
{
	cGameData *data = The_Game();	

	char GameTitle[256];
	sprintf(GameTitle, "%S",(const wchar_t *)data->GameTitle);
	char Motd[256];
	sprintf(Motd, "%S",(const wchar_t *)data->Motd);
	char MVPName[256];
	sprintf(MVPName, "%S",(const wchar_t *)data->MVPName);
	char Owner[256];
	sprintf(Owner, "%S",(const wchar_t *)data->Owner);
	char Password[256];
	sprintf(Password, "%S",(const wchar_t *)data->Password);
	char SettingsDescription[256];
	sprintf(SettingsDescription, "%S",(const wchar_t *)data->SettingsDescription);

	return Py_BuildValue("{s:i,s:I,s:I,s:i,s:i,s:I,s:I,s:i,s:I,s:s,s:i,s:s,s:I,s:f,s:I,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:s,s:I,s:I,s:f,s:I,s:s,s:s,s:u,s:s,s:s,s:s,s:I,s:I,s:i,s:s,s:i,s:i,s:I,s:f,s:i,s:I,s:I}",  //46
			"CanRepairBuildings", data->CanRepairBuildings, //1
			"CFGModTime", data->CFGModTime, //2
			"CurrentPlayers", data->CurrentPlayers, //3
			"DoMapsLoop", data->DoMapsLoop, //4
			"DriverIsAlwaysGunner", data->DriverIsAlwaysGunner, //5
			"FrameCount", data->FrameCount, //6
			"GameDuration_Seconds", data->GameDuration_Seconds, //7
			"GameplayPermitted", data->GameplayPermitted, //8
			"GameStartTime", data->GameStartTime, //9
			"GameTitle", GameTitle, //10
			"GrantWeapons", data->GrantWeapons, //11
			"INI", data->INI, //12
			"IntermissionTime_Seconds", data->IntermissionTime_Seconds, //13
			"IntermissionTimeLeft", data->IntermissionTimeLeft, //14
			"IP", data->IP, //15
			"IsAutoRestart", data->IsAutoRestart, //16
			"IsClanGame", data->IsClanGame, //17
			"IsDedicated", data->IsDedicated, //18
			"IsFriendlyFirePermitted", data->IsFriendlyFirePermitted, //19
			"IsLaddered", data->IsLaddered, //20
			"IsPassworded", data->IsPassworded, //21
			"IsQuickMatch", data->IsQuickMatch, //22
			"IsTeamChangingAllowed", data->IsTeamChangingAllowed, //23
			"MapCycleOver", data->MapCycleOver, //24
			"MapName", data->MapName, //25
			"MapNumber", data->MapNumber, //26
			"MaxPlayers", data->MaxPlayers, //27
			"MaxWorldDistance", data->MaxWorldDistance, //28
			"MinQualifyingTime_Minutes", data->MinQualifyingTime_Minutes, //29
			"ModName", data->ModName, //30
			"Motd", Motd, //31
			"MVPCount", data->MVPCount, //32
			"MVPName", MVPName, //33
			"Owner", Owner, //34
			"Password", Password, //35
			"Port", data->Port, //36
			"RadarMode", data->RadarMode, //37
			"RemixTeams", data->RemixTeams, //38
			SettingsDescription, data->SettingsDescription, //39
			"SpawnWeapons", data->SpawnWeapons, //40
			"StringVersionsMatch", data->StringVersionsMatch, //41
			"TimeLimit_Minutes", data->TimeLimit_Minutes, //42
			"TimeRemaining_Seconds", data->TimeRemaining_Seconds, //43
			"UseLagReduction", data->UseLagReduction, //44
			"WinnerID", data->WinnerID, //45
			"WinType", data->WinType); //6
}

PyObject* scriptsdll_getallobjects(PyObject *self, PyObject *args)
{
	PyObject* objectlist;

	objectlist = PyList_New(0);
	Py_INCREF(objectlist);

	for(GenericSLNode *x = BaseGameObjList->HeadNode; x; x = x->NodeNext)
	{
		GameObject *o = (GameObject *)x->NodeData;
		
		if ( -1 == PyList_Append(objectlist,Py_BuildValue("i", Helper::Get_ID(o))) )
		{
			printf("Error occured while trying to build list for Get_All_Objects().");
			return NULL;
		}
	}
	return objectlist;
}

PyObject* scriptsdll_getrotation(PyObject *self, PyObject *args)
{
	PyObject* objectlist;

	objectlist = PyList_New(0);
	Py_INCREF(objectlist);

	for(int i = 0;; i++)
	{
		const char *x = The_Game()->MapList[i];
		if(*x != 0)
		{
			if ( -1 == PyList_Append(objectlist,Py_BuildValue("s", x)) )
			{
				printf("Error occured while trying to build list for Get_Rotation().");
				return NULL;
			}
		}
		else
		{
			break;
		}
	}
	return objectlist;
}

PyObject* scriptsdll_getallvehicles(PyObject *self, PyObject *args)
{
	PyObject* objectlist;

	objectlist = PyList_New(0);
	Py_INCREF(objectlist);

	for(GenericSLNode *x = BaseGameObjList->HeadNode; x; x = x->NodeNext)
	{
		GameObject *o = (GameObject *)x->NodeData;
		if(!Is_Vehicle(o))
		{
			continue;
		}

		if ( -1 == PyList_Append(objectlist,Py_BuildValue("i", Helper::Get_ID(o))) )
		{
			printf("Error occured while trying to build list for Get_All_Vehicles().");
			return NULL;
		}
	}
	return objectlist;
}

PyObject* scriptsdll_getallplayers(PyObject *self, PyObject *args)
{
	PyObject* objectlist;

	objectlist = PyList_New(0);
	Py_INCREF(objectlist);

	for(GenericSLNode *x = PlayerList->HeadNode; x; x = x->NodeNext)
	{
		cPlayer *p = (cPlayer *)x->NodeData;
		if(!p->IsInGame || !p->IsActive)
		{
			continue;
		}

		if ( -1 == PyList_Append(objectlist,Py_BuildValue("i", p->PlayerId)) )
		{
			printf("Error occured while trying to build list for Get_All_Players().");
			return NULL;
		}
	}
	return objectlist;
}


PyObject* scriptsdll_getallbuildings(PyObject *self, PyObject *args)
{
	PyObject* objectlist;

	objectlist = PyList_New(0);
	Py_INCREF(objectlist);

	for(GenericSLNode *x = BuildingGameObjList->HeadNode; x; x = x->NodeNext)
	{
		GameObject *o = (GameObject *)x->NodeData;

		if ( -1 == PyList_Append(objectlist,Py_BuildValue("i", Helper::Get_ID(o))) )
		{
			printf("Error occured while trying to build list for Get_All_Buildings().");
			return NULL;
		}
	}
	return objectlist;
}