#include ".\pythoninclude\Python.h"
#include "scripts.h"
#include "engine.h"
#include "date.h"
#include "hooks.h"
#include "helper_functions.h"
#pragma warning( disable : 701 127 )

bool Hooks::Chat_Hook(int ID, int Type, WideStringClass &Msg2, int target) 
{
	PyObject* pFunc, *pTemp, *pArgs, *result;
	char buf[128];
	int temp, ret = 1;

	wcstombs(buf, Msg2.Peek_Buffer(), 100);
	pArgs = Py_BuildValue("(iisi)", ID, Type, buf, target);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		//printf("i = %i\n", i); // DEBUG CRAP
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnChat"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnChat");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
				Py_XDECREF(result);
				printf("\nError occured while trying to call OnChat in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
				PyErr_Clear();
				continue;
			}
			PyArg_ParseTuple(result, "i", &temp);
			if (temp == 0) 
				ret = 0;
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pFunc); // this one causes a crash after a few calls
	//Py_XDECREF(pTemp); // this one causes issues apparently
	Py_XDECREF(pArgs);
	return ret;
}

void Hooks::Version_Hook(int ID, float Ver)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(if)", ID, Ver);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnVersion"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnVersion");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call OnVersion in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

void Hooks::Player_Join_Hook(int ID, const char* Nick)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(is)", ID, Nick);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnPlayerJoin"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnPlayerJoin");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call OnPlayerJoin in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

void Hooks::Host_Hook(int ID, int Type, const char* Msg)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(iis)", ID, Type, Msg);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnHostMessage"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnHostMessage");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call OnHostMessage in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}


void Hooks::Player_Leave_Hook(int ID)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(i)", ID);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnPlayerLeave"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnPlayerLeave");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call OnPlayerLeave in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

void Hooks::Level_Loaded_Hook()
{
	PyObject* pFunc, *pTemp, *result;

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (PyObject_HasAttrString(pTemp, "OnLevelLoaded")) {
			pFunc = PyObject_GetAttrString(pTemp, "OnLevelLoaded");
			if (pFunc && PyCallable_Check(pFunc)) 
			{			
				result = PyObject_CallObject(pFunc, NULL);
				if (result == NULL)
				{
					Py_XDECREF(result);
					printf("\nError occured while trying to call OnConsoleOutput in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
					PyErr_Clear();
					continue;
				}
				Py_XDECREF(result);
			}
		}
		Py_XDECREF(pFunc);
	}
}

void Hooks::Console_Output_Hook(const char* Output)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(s)", Output);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnConsoleOutput"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnConsoleOutput");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
				Py_XDECREF(result);
				printf("\nError occured while trying to call OnConsoleOutput in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
				PyErr_Clear();
				continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

void Hooks::Purchase_Hook(BaseControllerClass *base, GameObject *purchaser, unsigned int cost, unsigned int preset,unsigned int purchaseret,const char *data)
{
/*	PyObject* pFunc, *pTemp, *pArgs, *result;

	//pArgs = Py_BuildValue("(iIII)", Helper::Get_ID(purchaser), cost, preset, purchaseret); //DEBUG CRAP

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, data))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, data);
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call %s in module %s. Bad arguments?\n", data, PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs); */ //DEBUG CRAP
}

void Hooks::Object_Hook(void *data, GameObject *obj)
{
	printf("size of modules array is = %i\n", ModulesArrayIndex); // DEBUG CRAP
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(i)", Helper::Get_ID(obj));

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		printf("entering 1\n"); // DEBUG CRAP
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnObjectCreate"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnObjectCreate");
		if (pFunc && PyCallable_Check(pFunc)) 
		{	
			printf("entering 2"); // DEBUG CRAP
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
				printf("entering 3"); // DEBUG CRAP
				Py_XDECREF(result);
				printf("\nError occured while trying to call OnObjectCreate in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
				PyErr_Clear();
				continue;
			}
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pTemp); // adding this causes errors
	Py_XDECREF(pArgs); 
}

void Hooks::DDE_Hook(const char *DDEStr)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(s)", DDEStr);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "OnDDE"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "OnDDE");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call OnDDE in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

void Hooks::Think_Hook()
{
	PyObject* pFunc, *pTemp;

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (PyObject_HasAttrString(pTemp, "OnThink")) {
			pFunc = PyObject_GetAttrString(pTemp, "OnThink");
			if (pFunc && PyCallable_Check(pFunc)) 
			{			
				PyObject_CallObject(pFunc, NULL);
			}
			else 
			{
				if (PyErr_Occurred())
				{
					PyErr_Print();
				}
				fprintf(stderr, "Cannot find function \"OnThink\"\n");
			}
		}
		Py_XDECREF(pFunc);
	}
}

void Hooks::Serial_Hook(int ID, const char *Serial)
{
	printf("serial hook triggered"); // DEBUG CRAP
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(is)", ID, Serial);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Serial_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Serial_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call Serial_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pTemp);  // DEBUG CRAP
	Py_XDECREF(pArgs);
}



void Hooks::LoadingE_Hook(int ID, bool Loaded)
{
	printf("pID = %i, loaded = %i", ID, Loaded); // DEBUG CRAP
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(ii)", ID, Loaded);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Loading_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Loading_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call Loading_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	// Py_XDECREF(pTemp); // DEBUG CRAP
	Py_XDECREF(pArgs);
}

bool Hooks::Damage_Hook(int ID, int Damager, int Target, float Damage, unsigned int Warhead)
{
	printf("damage hook triggered\n"); // DEBUG CRAP
	PyObject* pFunc, *pTemp, *pArgs, *result;
	int temp, ret = 1;

	pArgs = Py_BuildValue("(iiifI)", ID, Damager, Target, Damage, Warhead);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Damage_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Damage_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{	
			printf("entering Damage_Hook 1"); // DEBUG CRAP
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call Damage_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			PyArg_ParseTuple(result, "i", &temp);
			if (temp == 0) 
				ret = 0;
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pTemp);  // DEBUG CRAP
	Py_XDECREF(pArgs);
	return ret;
}

void Hooks::Ping_Hook(int ID, int Ping)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;

	pArgs = Py_BuildValue("(ii)", ID, Ping);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Ping_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Ping_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
			Py_XDECREF(result);
			printf("\nError occured while trying to call Ping_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
			PyErr_Clear();
			continue;
			}
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pTemp); 
	Py_XDECREF(pArgs);
}

bool Hooks::Suicide_Hook(int ID)
{
	PyObject* pFunc, *pTemp, *pArgs, *result;
	int temp, ret = 1;

	pArgs = Py_BuildValue("(i)", ID);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		//printf("i = %i\n", i); // DEBUG CRAP
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Suicide_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Suicide_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{			
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
				Py_XDECREF(result);
				printf("\nError occured while trying to call Suicide_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
				PyErr_Clear();
				continue;
			}
			PyArg_ParseTuple(result, "i", &temp);
			if (temp == 0) 
				ret = 0;
			Py_XDECREF(result);
		}
	}
	//Py_XDECREF(pTemp);
	Py_XDECREF(pArgs);
	return ret;
}

bool Hooks::Radio_Hook(int Team, int PlayerId, int a, int RadioId, int b)
{
	printf("entering start radio hook\n"); // DEBUG CRAP
	PyObject* pFunc, *pTemp, *pArgs, *result;
	int temp, ret = 1;

	pArgs = Py_BuildValue("(iiiii)", Team, PlayerId, a, RadioId, b);

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		printf("entering 1\n"); // DEBUG CRAP
		pTemp = ModulesArray[i];
		if (!PyObject_HasAttrString(pTemp, "Radio_Hook"))
			continue;
		pFunc = PyObject_GetAttrString(pTemp, "Radio_Hook");
		if (pFunc && PyCallable_Check(pFunc)) 
		{		
			printf("entering 2\n"); // DEBUG CRAP
			result = PyObject_CallObject(pFunc, pArgs);
			if ( result == NULL)
			{
				printf("entering 3\n"); // DEBUG CRAP
				//Py_XDECREF(result);
				printf("\nError occured while trying to call Radio_Hook in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
				PyErr_Clear();
				//continue; 
			}
			PyArg_ParseTuple(result, "i", &temp);
			printf("ret == %d", temp);
			if (temp == 0) 
				ret = 0;
			Py_XDECREF(result); 
		}
	}
	//Py_XDECREF(pTemp); DEBUG CRAP
	Py_XDECREF(pArgs); 
	return ret;
}

void Hooks::GameOver_Hook()
{
	PyObject* pFunc, *pTemp, *result;

	for( int i = 0; i < ModulesArrayIndex; ++i)
	{
		printf("entering 1"); // DEBUG CRAP
		pTemp = ModulesArray[i];
		if (PyObject_HasAttrString(pTemp, "OnGameOver")) {
			pFunc = PyObject_GetAttrString(pTemp, "OnGameOver");
			if (pFunc && PyCallable_Check(pFunc)) 
			{			
				result = PyObject_CallObject(pFunc, NULL);
				printf("entering 2"); // DEBUG CRAP
				if (result == NULL)
				{
					printf("entering 4"); // DEBUG CRAP
					Py_XDECREF(result);
					printf("\nError occured while trying to call OnConsoleOutput in module %s. Bad arguments?\n", PyModule_GetFilename(pTemp));
					PyErr_Clear();
					continue;
				}
				Py_XDECREF(result);
			}
		}
		Py_XDECREF(pFunc);
	}
}

