#include <nms_common.h>
#include <nms_util.h>
#include <nms_core.h>
#include <nxmodule.h>
#include <nxvs_common.h>

#ifdef _WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif   /* _WIN32 */


//
// Helper functions to start command handler in new thread
//

typedef struct
{
	void (*m_handler)(CSCPMessage *, ClientSession *);
	CSCPMessage *m_msg;
	ClientSession *m_session;
} PROCESSING_THREAD_DATA;

static THREAD_RESULT THREAD_CALL ProcessingThread(void *arg)
{
	PROCESSING_THREAD_DATA *data = (PROCESSING_THREAD_DATA *)arg;

	data->m_handler(data->m_msg, data->m_session);
	delete data->m_msg;
	data->m_session->decRefCount();
	free(data);
	return THREAD_OK;
}

static void StartCommandHandler(void (*pfHandler)(CSCPMessage *, ClientSession *),
										  CSCPMessage *msg, ClientSession *session)
{
	PROCESSING_THREAD_DATA *data;

	data = (PROCESSING_THREAD_DATA *)malloc(sizeof(PROCESSING_THREAD_DATA));
	data->m_handler = pfHandler;
	data->m_msg = msg;
	data->m_session = session;
	ThreadCreate(ProcessingThread, 0, data);
}


//
// Example command handler
//

static void SendUserRights(DWORD requestId, ClientSession *session)
{
	CSCPMessage msg;

	msg.SetCode(CMD_REQUEST_COMPLETED);
	msg.SetId(requestId);
	msg.SetVariable(VID_RCC, RCC_SUCCESS);
	msg.SetVariable(VID_NXVS_USER_RIGHTS, GetNXVSUserRights(session->getUserId()));
	session->sendMessage(&msg);
}


//
// Command handler
// Parameters:
//     command - command code
//     msg - message received from client
//     session - client session (can be used for access rights validation and sending response)
//

static int CommandHandler(DWORD command, CSCPMessage *msg, ClientSession *session)
{
	// All client commands not recognized by core passed to modules
	// Command handler must return one of the following, depending on taken action:
	//
	// NXMOD_COMMAND_PROCESSED - command was processed
	// NXMOD_COMMAND_ACCEPTED_ASYNC - command accepted by module and will be processed in separate thread
	// NXMOD_COMMAND_IGNORED - command ignored by module. In that case command will be passed to next module in the list.
	
	if (command == CMD_GET_NXVS_USER_RIGHTS)
	{
		SendUserRights(msg->GetId(), session);
		return NXMOD_COMMAND_PROCESSED;
	}
	
	return NXMOD_COMMAND_IGNORED;
}


//
// Event handler
//

static BOOL EventHandler(Event *event)
{
	// Events can be handled here
	// All events are passed to modules after processing by correlation engine and before 
	// processing by event processing policy and logging
	// Return value currently ignored
	return TRUE;
}


//
// Module entry point
//

extern "C" BOOL EXPORT NetXMSModuleInit(NXMODULE *module)
{
	// Module should do all required initialization here
	// If module requires some background processing, additional threads can be started here
	// Functions DbgPrintf and WriteLogOther can be used for logging
	
	module->dwSize = sizeof(NXMODULE);
	_tcscpy(module->szName, _T("DEMO"));
	module->pfCommandHandler = CommandHandler;
	module->pfEventHandler = EventHandler;
	
	DbgPrintf(3, _T("Some debug info"));
	WriteLogOther(NXLOG_INFO, _T("Module initialization complete"));

	return TRUE;
}


//
// DLL Entry point
//

#ifdef _WIN32

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
   if (dwReason == DLL_PROCESS_ATTACH)
      DisableThreadLibraryCalls(hInstance);
   return TRUE;
}

#endif
