/*

Miranda NG: the free IM client for Microsoft* Windows*

Copyright (�) 2012-17 Miranda NG project (http://miranda-ng.org)
Copyright (c) 2000-08 Miranda ICQ/IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#ifndef M_MESSAGE_H__
#define M_MESSAGE_H__ 1

#include <m_database.h>

extern int hLangpack;

// brings up the send message dialog for a contact
// wParam = (MCONTACT)hContact
// lParam = (LPARAM)(char*)szText
// returns 0 on success or nonzero on failure
// returns immediately, just after the dialog is shown
// szText is the text to put in the edit box of the window (but not send)
// szText = NULL will not use any text
// szText != NULL is only supported on v0.1.2.0+
#define MS_MSG_SENDMESSAGE   "SRMsg/SendCommand"
#define MS_MSG_SENDMESSAGEW  "SRMsg/SendCommandW"

#define ME_MSG_WINDOWEVENT "MessageAPI/WindowEvent"
// wparam = 0
// lparam = (WPARAM)(MessageWindowEventData*)hWindowEvent;
// Event types
#define MSG_WINDOW_EVT_OPENING 1 //window is about to be opened
#define MSG_WINDOW_EVT_OPEN    2 //window has been opened
#define MSG_WINDOW_EVT_CLOSING 3 //window is about to be closed
#define MSG_WINDOW_EVT_CLOSE   4 //window has been closed
#define MSG_WINDOW_EVT_CUSTOM  5 //custom event for message plugins to use (custom uFlags may be used)

#define MSG_WINDOW_UFLAG_MSG_FROM 0x00000001
#define MSG_WINDOW_UFLAG_MSG_TO   0x00000002
#define MSG_WINDOW_UFLAG_MSG_BOTH 0x00000004

typedef struct {
	int cbSize;
	MCONTACT hContact;
	HWND hwndWindow; // top level window for the contact
	const char* szModule; // used to get plugin type (which means you could use local if needed)
	unsigned int uType; // see event types above
	unsigned int uFlags; // used to indicate message direction for all event types except custom
	void *local; // used to store pointer to custom data
	HWND hwndInput; // input area window for the contact (or NULL if there is none)
	HWND hwndLog; // log area window for the contact (or NULL if there is none)
} MessageWindowEventData;

typedef struct {
	int cbSize;
	HICON hIcon; 
	wchar_t tszText[100];
} StatusTextData;

// wparam = (MCONTACT)hContact
// lparam = (StatusTextData*) or NULL to clear statusbar
// Sets a statusbar line text for the appropriate contact
#define MS_MSG_SETSTATUSTEXT "MessageAPI/SetStatusText"

// wparam = 0
// lparam = 0
// Returns a dword with the current message api version
// Current version is 0, 0, 0, 4
#define MS_MSG_GETWINDOWAPI "MessageAPI/WindowAPI"

// wparam = (char*)szBuf
// lparam = (int)cbSize size of buffer
// Sets the window class name in wParam (ex. "SRMM" for srmm.dll)
#define MS_MSG_GETWINDOWCLASS "MessageAPI/WindowClass"

typedef struct {
	int cbSize;
	MCONTACT hContact;
	int uFlags; // see uflags above
} MessageWindowInputData;

#define MSG_WINDOW_STATE_EXISTS  0x00000001 // Window exists should always be true if hwndWindow exists
#define MSG_WINDOW_STATE_VISIBLE 0x00000002
#define MSG_WINDOW_STATE_FOCUS   0x00000004
#define MSG_WINDOW_STATE_ICONIC  0x00000008

typedef struct {
	int cbSize;
	MCONTACT hContact;
	int uFlags;  // should be same as input data unless 0, then it will be the actual type
	HWND hwndWindow; //top level window for the contact or NULL if no window exists
	int uState; // see window states
	void *local; // used to store pointer to custom data
} MessageWindowData;

// wparam = (MessageWindowInputData*)
// lparam = (MessageWindowData*)
// returns 0 on success and returns non-zero (1) on error or if no window data exists for that hcontact
#define MS_MSG_GETWINDOWDATA "MessageAPI/GetWindowData"

// wparam = 0 (unused)
// lparam = (MessageWindowEvent*)
// fired before SRMM writes an entered message into the database
#define ME_MSG_PRECREATEEVENT    "MessageAPI/PreCreateEvent"

typedef struct {
	int cbSize;
	int seq;      // number returned by PSS_MESSAGE
	MCONTACT hContact;
	DBEVENTINFO *dbei; // database event written on the basis of message sent
} MessageWindowEvent;

/////////////////////////////////////////////////////////////////////////////////////////
// SRMM popup menu

// wParam = 0
// lParam = (MessageWindowPopupData *)&MessageWindowPopupData;
// Fired to allow plugins to add items to the msg window popup menu
// Always fired twice: once with MSG_WINDOWPOPUP_SHOWING and once with MSG_WINDOWPOPUP_SELECTED.
// This is done to allow cleaning of resources.

#define ME_MSG_WINDOWPOPUP		"MessageAPI/WindowPopupRequested"

#define MSG_WINDOWPOPUP_SHOWING  1
#define MSG_WINDOWPOPUP_SELECTED 2

#define MSG_WINDOWPOPUP_INPUT    1
#define MSG_WINDOWPOPUP_LOG      2

typedef struct {
	int cbSize;
	unsigned int uType; // see popup types above
	unsigned int uFlags; // used to indicate in which window the popup was requested
	MCONTACT hContact;
	HWND hwnd; // window where the popup was requested
	HMENU hMenu;	// The handle to the menu
	POINT pt; // The point, in screen coords
	int selection; // The menu control id or 0 if no one was selected
} MessageWindowPopupData;

/////////////////////////////////////////////////////////////////////////////////////////
// status icons

#define MBF_DISABLED       0x01
#define MBF_HIDDEN         0x02
#define MBF_UNICODE        0x04

typedef struct {
	int   cbSize;                    // must be equal to sizeof(StatusIconData)
	char *szModule;                  // used in combo with the dwId below to create a unique identifier
	DWORD dwId;                      // uniquely defines a button inside a module
	HICON hIcon, hIconDisabled;      // hIconDisabled is optional - if null, will use hIcon in the disabled state
	int   flags;                     // bitwize OR of MBF_* flags above
	union {
		char *szTooltip;              // controlled by MBF_UNICODE
		wchar_t *tszTooltip;
		wchar_t *wszTooltip;
	};
} StatusIconData;

#define MBCF_RIGHTBUTTON   0x01     // if this flag is specified, the click was a right button - otherwize it was a left click

// adds an icon
EXTERN_C MIR_APP_DLL(int) Srmm_AddIcon(StatusIconData *sid, int _hLang = hLangpack);

// removes an icon
EXTERN_C MIR_APP_DLL(void) Srmm_RemoveIcon(const char *szProto, DWORD iconId);

// if hContact is null, icon is modified for all contacts
// otherwise, only the flags field is valid
// if either hIcon, hIconDisabled or szTooltip is null, they will not be modified
EXTERN_C MIR_APP_DLL(int) Srmm_ModifyIcon(MCONTACT hContact, StatusIconData *sid);

// wParam = (HANDLE)hContact
// lParam = (int)zero-based index of a visible icon
// returns (StatusIconData*)icon description filled for the required contact
// don't free this memory.
EXTERN_C MIR_APP_DLL(StatusIconData*) Srmm_GetNthIcon(MCONTACT hContact, int index);

/////////////////////////////////////////////////////////////////////////////////////////
// status icons click notification

struct StatusIconClickData
{
	int   cbSize;
	POINT clickLocation;             // click location, in screen coordinates
	char *szModule;
	DWORD dwId;
	int   flags;                       // bitwize OR of MBCF_* flags above
};

// wParam = (HANDLE)hContact;
// lParam = (StatusIconClickData *)&StatusIconClickData;
// catch to show a popup menu, etc.
#define ME_MSG_ICONPRESSED		"MessageAPI/IconPressed"

// wParam = (HANDLE)hContact;
// lParam = (StatusIconkData*)pIcon
// catch to be notified about the icon list's change.
#define ME_MSG_ICONSCHANGED   "MessageAPI/IconsChanged"

/////////////////////////////////////////////////////////////////////////////////////////
// srmm toolbar icons' support

// button state flags
#define BBSF_HIDDEN           (1<<0)
#define BBSF_DISABLED         (1<<1)
#define BBSF_PUSHED           (1<<2)
#define BBSF_RELEASED         (1<<3)

// button flags
#define BBBF_DISABLED			(1<<0)
#define BBBF_HIDDEN				(1<<1)
#define BBBF_ISPUSHBUTTON		(1<<2)
#define BBBF_ISARROWBUTTON		(1<<3)
#define BBBF_ISCHATBUTTON		(1<<4)
#define BBBF_ISIMBUTTON			(1<<5)
#define BBBF_ISRSIDEBUTTON		(1<<7)
#define BBBF_CANBEHIDDEN		(1<<8)
#define BBBF_ISSEPARATOR		(1<<9)
#define BBBF_CANTBEHIDDEN		(1<<10)
#define BBBF_CREATEBYID			(1<<11)  // only for the internal use

struct BBButton
{
	const char    *pszModuleName;  // module name without spaces and underline symbols (e.g. "tabsrmm")
	DWORD          dwButtonID;     // your button ID, will be combined with pszModuleName for storing settings, etc...

	const wchar_t *pwszText;       // button's text, might be NULL
	const wchar_t *pwszTooltip;    // button's tooltip, might be NULL
	DWORD          dwDefPos;       // default order pos of button, counted from window edge (left or right)
	                               // use value >100, because internal buttons using 10,20,30... 80, etc
	DWORD          bbbFlags;       // combine of BBBF_ flags above
	HANDLE         hIcon;          // Handle to icolib registered icon
};

// adds a new toolbar button
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(int) Srmm_AddButton(const BBButton *bbdi, int = hLangpack);

// modifies the existing toolbar button
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(int) Srmm_ModifyButton(BBButton *bbdi);

// removes a toolbar button identified by a structure
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(int) Srmm_RemoveButton(BBButton *bbdi);

// retrieves data from a toolbar button to a structure
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(int) Srmm_GetButtonState(HWND hwndDlg, BBButton *bbdi);

// applies a new data to a toolbar button
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(int) Srmm_SetButtonState(MCONTACT hContact, BBButton *bbdi);

// resets toolbar settings to these default values
// returns 0 on success and nonzero value otherwise
EXTERN_C MIR_APP_DLL(void) Srmm_ResetToolbar();

// creates toolbar buttons for a SRMM window
// flags might be either BBBF_ISIMBUTTON or BBBF_ISCHATBUTTON, depending on a window type
EXTERN_C MIR_APP_DLL(void) Srmm_CreateToolbarIcons(HWND hwndDlg, int flags);

// updates all toolbar icons in a message dialog
EXTERN_C MIR_APP_DLL(void) Srmm_UpdateToolbarIcons(HWND hdlg);

// draws all toolbar icons in a message dialog
EXTERN_C MIR_APP_DLL(void) Srmm_RedrawToolbarIcons(HWND hwndDlg);

// ToolBar loaded event
// This event will be send after module loaded and after each toolbar reset
// You should add your buttons on this event
#define ME_MSG_TOOLBARLOADED "SRMM/ButtonsBar/ModuleLoaded"

/////////////////////////////////////////////////////////////////////////////////////////
// toolbar button clicked event

EXTERN_C MIR_APP_DLL(void) Srmm_ClickToolbarIcon(MCONTACT hContact, DWORD idFrom, HWND hwndFrom, BOOL code);

// wParam = (HANDLE)hContact;
// lParam = (CustomButtonClickData*) pointer to the click data;
// catch to show a popup menu, etc.
#define ME_MSG_BUTTONPRESSED "SRMM/ButtonsBar/ButtonPressed"

// event flags
#define BBCF_RIGHTBUTTON	(1<<0)
#define BBCF_SHIFTPRESSED	(1<<1)
#define BBCF_CONTROLPRESSED	(1<<2)
#define BBCF_ARROWCLICKED	(1<<3)

struct CustomButtonClickData
{
	char    *pszModule;   // button owners name
	POINT    pt;          // screen coordinates for menus
	DWORD    dwButtonId;  // registered button ID
	HWND     hwndFrom;    // button parents HWND
	MCONTACT hContact;
	DWORD    flags;       // BBCF_ flags
};

/////////////////////////////////////////////////////////////////////////////////////////
// toolbar button internal representation

#define MIN_CBUTTONID      4000
#define MAX_CBUTTONID      5000

#define BBSF_IMBUTTON		(1<<0)
#define BBSF_CHATBUTTON		(1<<1)
#define BBSF_CANBEHIDDEN	(1<<2)
#define BBSF_NTBSWAPED		(1<<3)
#define BBSF_NTBDESTRUCT	(1<<4)

struct CustomButtonData : public MZeroedObject
{
	~CustomButtonData()
	{}

	DWORD  m_dwPosition;    // default order pos of button, counted from window edge (left or right)

	DWORD  m_dwButtonOrigID; // id of button used while button creation and to store button info in DB
	ptrA   m_pszModuleName;  // module name without spaces and underline symbols (e.g. "tabsrmm")

	DWORD  m_dwButtonCID;
	DWORD  m_dwArrowCID;    // only use with BBBF_ISARROWBUTTON flag

	ptrW   m_pwszText;      // button's text
	ptrW   m_pwszTooltip;   // button's tooltip

	int    m_iButtonWidth;  // must be 22 for regular button and 33 for button with arrow
	HANDLE m_hIcon;         // Handle to icolib registred icon

	bool   m_bIMButton, m_bChatButton;
	bool   m_bCanBeHidden, m_bCantBeHidden, m_bHidden, m_bAutoHidden, m_bSeparator, m_bDisabled, m_bPushButton;
	bool   m_bRSided;
	BYTE   m_opFlags;
	int    m_hLangpack;
};

// gets the required button or NULL, if i is out of boundaries
EXTERN_C MIR_APP_DLL(CustomButtonData*) Srmm_GetNthButton(int i);

// retrieves total number of toolbar buttons
EXTERN_C MIR_APP_DLL(int) Srmm_GetButtonCount(void);

// these messages are sent to the message windows if toolbar buttons are changed
#define WM_CBD_FIRST   (WM_USER+0x600)

// wParam = 0 (ignored)
// lParam = (CustomButtonData*)pointer to button or null if any button can be changed
#define WM_CBD_UPDATED (WM_CBD_FIRST+1)

// wParam = button id
// lParam = (CustomButtonData*)pointer to button
#define WM_CBD_REMOVED (WM_CBD_FIRST+2)

// wParam = 0 (ignored)
// lParam = 0 (ignored)
#define WM_CBD_LOADICONS (WM_CBD_FIRST+3)

#endif // M_MESSAGE_H__