// this is the "glue" to C4D...
// please modify only if you know exactly what you are doing...

#ifdef __PC
	#include <windows.h>
#endif

#include "c4d_plugin.h"
#include "c4d_file.h"
#include "c4d_resource.h"

#ifdef __MAC
	#ifdef __cplusplus
	extern "C" {
	#endif

	#define C4D_MAIN LONG __attribute__((visibility("default"))) c4d_main(LONG action, void* p1, void* p2, void* p3)
	C4D_MAIN;

	#ifdef __cplusplus
	}
	#endif
#elif defined __PC
  HINSTANCE g_hinstDLL;
  LPVOID g_lpReserved;

	#ifdef __cplusplus
	extern "C" {
	#endif

	#define C4D_MAIN LONG __declspec(dllexport) c4d_main(LONG action, void* p1, void* p2, void* p3)
	C4D_MAIN;

	#ifndef __WINCRTINIT
	BOOL APIENTRY DllMain(HANDLE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
	{
		switch (ul_reason_for_call)
		{
			case DLL_PROCESS_ATTACH:
				g_hinstDLL = (HINSTANCE)hModule;
				g_lpReserved = lpReserved;
			//case DLL_THREAD_ATTACH:
			//case DLL_THREAD_DETACH:
			//case DLL_PROCESS_DETACH:
				break;
		}
	  return TRUE;
	}

	#else
  extern BOOL APIENTRY _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);

  BOOL APIENTRY DllMainCRTStartup( HINSTANCE hinst, DWORD reason, LPVOID reserved )
	{
		g_hinstDLL = hinst;
		g_lpReserved = reserved;
		return TRUE;
	}
	#endif
	#ifdef __cplusplus
	}
	#endif
#else
	#ifdef __cplusplus
	extern "C" {
	#endif

	#define C4D_MAIN __attribute__ ((visibility("default"))) LONG c4d_main(LONG action, void* p1, void* p2, void* p3)
	C4D_MAIN;

	#ifdef __cplusplus
	}
	#endif
#endif

LONG InitOS(void *p);

Filename *path_storage;

C4D_MAIN //(LONG action, void* p1, void* p2, void* p3)
{
	static LONG init_count = 0;

	switch (action)
	{
		case C4DPL_INIT_VERSION:
		{
			#ifdef __SINGLEPRECISION
				return C4DPL_VERSION|C4DPL_SINGLEPRECISION_PLUGIN;
			#else
				return C4DPL_VERSION;
			#endif
		}

		case C4DPL_INIT_SYS:
			init_count += 1;
			if (init_count == 1)
			{
				if (InitOS(p1) < API_VERSION) return C4DPL_ERROR_VERSION;
        #ifdef __PC
					#ifdef __WINCRTINIT
						_CRT_INIT(g_hinstDLL, DLL_PROCESS_ATTACH, g_lpReserved);
					#endif
				#elif defined __MAC
					// static initializers are called by __dyld_dlopen, nothing to do here
				#endif
				if (!p3) return C4DPL_ERROR_VERSION;

				path_storage = gNew Filename;
				if (path_storage) *path_storage = *(Filename*)p3;
			}
			return 1;

		case C4DPL_MESSAGE:
			if (!PluginMessage((VLONG)p1,p2)) return C4DPL_ERROR;
			return 1;

		case C4DPL_INIT:
			return PluginStart();

		case C4DPL_END:
			init_count -= 1;
			if (init_count == 0)
			{
				PluginEnd();
				FreeResource();
				gDelete(path_storage);
        #ifdef __PC
					#ifdef __WINCRTINIT
						_CRT_INIT(g_hinstDLL, DLL_PROCESS_DETACH, g_lpReserved);
					#endif
				#elif defined __MAC
					// static destructors are called by __dyld_dlclose, nothing to do here
				#endif
			}
			return 1;

		default:
			break;
	}

	return C4DPL_ERROR;
}

