#ifndef _OPT_PLUGIN_H_INCLUDED_
#define _OPT_PLUGIN_H_INCLUDED_

// device OLED dimensions and buttons count

#define IMG_X_SIZE 96
#define IMG_Y_SIZE 96
#define MAX_BUTTON 3 

// string information to be provided by plug-in

#define INFO_KEY				0
#define INFO_NAME				1
#define INFO_DESC				2
#define INFO_AUTHOR				3
#define INFO_EMAIL				4
#define INFO_HOMEPAGE			5
#define INFO_APPLICATION		6
#define INFO_APPLICATION_CONFIG	7

// integer information to be provided by plug-in

// number of functions supported by plug-in
#define INFO_FUNCTIONS		10
// interval between paint calls
#define INFO_DELAY			11
// function will be set on plug-in drag
#define INFO_MAIN_FUNCTION  12

// HICON information to be provided by plug-in
#define INFO_ICON16			20
#define INFO_ICON32			21
#define INFO_DEFIMAGE		22

// information if plug-in has values to be saved in registry
#define INFO_HAS_PROPERTIES			0x100-1
#define INFO_HAS_SHARED_PROPERTIES	0x200-1

// properties bases. first has PLUGIN_PROPERTIES index, second PLUGIN_PROPERTIES+1, and so on
#define PLUGIN_PROPERTIES			0x100
#define PLUGIN_SHARED_PROPERTIES	0x200

// these are events plug-in can react on. 
#define EVENT_ACTIVATE		1
#define EVENT_DEACTIVATE	2

#define MAX_INFO_STRING     256
#define MAX_PROPERTY_LENGTH 256

// Defines to simplify GetInfo method programming

#define GET_INFO( INDEX, VALUE )						\
	if ( index == INDEX ){								\
		return (LPARAM)(VALUE);							\
	}

#define GET_ICON_SIZE( INDEX, VALUE, SIZE )				\
	if ( index == INDEX ){								\
		return (LPARAM)::LoadImage ( g_hModule, VALUE, IMAGE_ICON, SIZE, SIZE, LR_DEFAULTCOLOR ); \
	}

#define GET_ICON( INDEX, VALUE )						\
	GET_ICON_SIZE(INDEX, VALUE, 0)

#define GET_ICON_EX( VALUE )							\
	GET_ICON_SIZE( INFO_ICON16, VALUE, 16 )				\
	GET_ICON_SIZE( INFO_ICON32, VALUE, 32 )				

#define GET_IMAGE( INDEX, VALUE )						\
	if ( index == INDEX ){								\
		return (LPARAM)::LoadImage ( g_hModule, VALUE, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ); \
	}

// Defines to simplify GetProperty/SetProperty methods programming

#define GET_PROPERTY( INDEX, NAME, VALUE )				\
	if ( index == PLUGIN_PROPERTIES + INDEX ){			\
		strncpy( name, NAME, MAX_PROPERTY_LENGTH );		\
		strncpy( value, VALUE, MAX_PROPERTY_LENGTH );	\
		return TRUE;									\
	}

#define GET_INT_PROPERTY( INDEX, NAME, VALUE )			\
	if ( index == PLUGIN_PROPERTIES + INDEX ){			\
		strncpy( name, NAME, MAX_PROPERTY_LENGTH );		\
		itoa(VALUE,value,10);							\
		return TRUE;									\
	}

#define SET_PROPERTY( NAME, VALUE )						\
	if ( !strncmp(name, NAME, MAX_PROPERTY_LENGTH) ){	\
		VALUE = value;									\
		return TRUE;									\
	}

#define SET_INT_PROPERTY( NAME, VALUE )					\
	if ( !strncmp(name, NAME, MAX_PROPERTY_LENGTH) ){	\
		VALUE = atoi(value);							\
		return TRUE;									\
	}

#define GET_SHARED_PROPERTY( INDEX, NAME, VALUE )		\
	if ( index == PLUGIN_SHARED_PROPERTIES + INDEX ){	\
		strncpy( name, NAME, MAX_PROPERTY_LENGTH );		\
		strncpy( value, VALUE, MAX_PROPERTY_LENGTH );	\
		return TRUE;									\
	}


// This is the interface plug-in should implement. Plug-in DLL has Create and Delete methods exported,
// Create should return a pointer to class derived from OptimusMiniPlugin class, 
// Delete should release memory for created object.

class OptimusMiniPlugin
{
public:
	// Constructor should create an object for specified function.
	// Each function should provide it's own icons and description information.
	// Multi-function plug-ins displayed as a tree with function=0 as the root node.
	// OptimusMiniPlugin(int function) = 0;

	// called every INFO_DELAY ms or three times a second by default.
	// should return true if anything painted, false means previous image should be used.	
	// HDC:  has IMG_X_SIZE x IMG_Y_SIZE dimensions
	virtual BOOL __stdcall Paint(HDC hdc) = 0;

	// called on keydown from device thread. should return fast.
	virtual void __stdcall OnKeyDown() = 0;

	// to collect INFO_* values from plug-in
	virtual LPARAM __stdcall GetInfo(int index) = 0;

	// allows to get properties from plug-in instance
	// index: from PLUGIN_PROPERTIES and PLUGIN_SHARED_PROPERTIES until false is return.
	// should return value and name (no longer then MAX_PROPERTY_LENGTH bytes)
	virtual BOOL __stdcall GetProperty(int index, char *name, char *value){ return FALSE; }

	// allows to set plug-in instance properties
	// called for every name got with GetProperty with actial value from registry
	virtual BOOL __stdcall SetProperty(const char *name, const char *value){ return FALSE; }

	// shows plug-in properties dialog.
	// should return true if properties has been changed.
	virtual BOOL __stdcall ShowProperties(HWND hwnd){ return FALSE; }

	// plug-in life cicle is OnEvent(ACTIVATE) -> Paint(),Paint().. -> OnEvent(DEACTIVATE)
	// ACTIVATE/DEACTIVATE can be used to allocate resources requied for painting
	// should return TRUE. should return fast.
	virtual BOOL __stdcall OnEvent(int event){ return TRUE; }
};

extern HMODULE g_hModule;

// define to create the exported Create and Delete functions
#define PLUGIN_EXPORT(type)		                                                             \
HMODULE g_hModule = NULL;												                     \
extern "C" __declspec(dllexport) OptimusMiniPlugin *Create( HMODULE hModule, int function, LPARAM Reserved )  \
{																				             \
	g_hModule = hModule;                                                                     \
	type *lpPlugin = new type(function);												     \
	return lpPlugin;															             \
}                                                                                            \
extern "C" __declspec(dllexport) void Delete( OptimusMiniPlugin* lpPlugin )                  \
{																				             \
	delete static_cast<type*>(lpPlugin);	        									     \
}


#endif	//_OPT_PLUGIN_H_INCLUDED_
