#pragma once
#include <vector>
#include "ZJIMDef.h"


#define WM_SYSNOTIFY_CLICKED					(WM_USER + 100)
#define WM_MAINTAB_SELECTED						(WM_USER + 101)
#define WM_MAINTAB_UNSELECTED					(WM_USER + 102)
#define WM_MAINTAB_SIZE							(WM_USER + 103)


typedef struct tagEIMTABSELCHANGED
{
	HWND	hContainerWnd;
	RECT	rtContainerClient;

	tagEIMTABSELCHANGED(HWND hWnd, const RECT& rect)
		: hContainerWnd(hWnd)
		, rtContainerClient(rect)
	{
	}

}EIMTABSELCHANGED, *LPEIMTABSELCHANGED;


enum PluginChildWndPosition
{
	Plugin_Child_Center,
	Plugin_Child_Attach,
};

#define EIM_SLOT_MAINFRM_TOP_TOOLBAR			0x0001
#define EIM_SLOT_MAINFRM_BOTTOM_TOOLBAR			0x0002
#define EIM_SLOT_CHATDLG_TOP_TOOLBAR			0x0004
#define EIM_SLOT_CHATDLG_EDIT_TOOLBAR			0x0008
#define EIM_SLOT_TRIBEDLG_TOP_TOOLBAR			0x0010
#define EIM_SLOT_TRIBEDLG_EDIT_TOOLBAR			0x0020
#define EIM_SLOT_MAINFRM_TAB					0x0040
#define EIM_SLOT_NAMECARD_TOOLBAR				0x0080


#define ID_PLUGIN_ITEM_FIRST			50000
#define ID_PLUGIN_ITEM_LAST				59999


#define EIM_CONTACT_ID_MAX_LEN			32
#define EIM_CONTACT_NAME_MAX_LEN		32

// 插件对象
typedef struct tagEIMPluginInfo
{
	TCHAR			szPluginGuid[33];
	TCHAR			szPluginName[32];
	TCHAR			szPluginDesc[256];
	TCHAR			szPluginComp[32];
	TCHAR			szPluginUrl[64];
	UINT			nSlotItems;
}EIMPluginInfo, *LPEIMPluginInfo;

// 插槽区对象
typedef struct tagEIMSlotItemInfo
{
	SHORT			nSlotItemInnerID;
	UINT			nSlotItemType;
	TCHAR			szSlotItemIcon[32];
	TCHAR			szSlotItemText[32];
	TCHAR			szSlotItemToolTip[64];
	UINT			nSlotItemMenu;
	UINT			nSlotItemWnd;

	tagEIMSlotItemInfo()
		: nSlotItemInnerID(0)
		, nSlotItemType(0)
		, nSlotItemMenu(0)
		, nSlotItemWnd(0)
	{
	}

}EIMSlotItemInfo, *LPEIMSlotItemInfo;

struct IEIMPluginBaseProc;
struct IEIMPluginMessageProc;
struct IEIMPluginNotifyProc;

// EIM插件管理器接口
struct IEIMPluginManager
{
	virtual UINT AddSlotItem(LPCTSTR strCurrentPluginPath, UINT nPluginID, const EIMSlotItemInfo& item) = 0;

	virtual BOOL RemoveSlotItem(UINT nPluginID, UINT nItemID) = 0;

	virtual BOOL AddBaseProc(UINT nPluginID, IEIMPluginBaseProc* pBaseProc) = 0;

	virtual void RemoveBaseProc(UINT nPluginID, IEIMPluginBaseProc* pBaseProc) = 0;

	virtual BOOL AddMessageProc(UINT nPluginID, IEIMPluginMessageProc* pMessageProc) = 0;

	virtual void RemoveMessageProc(UINT nPluginID, IEIMPluginMessageProc* pMessageProc) = 0;

	virtual BOOL AddPluginNotifyProc(UINT nPluginID, LPCTSTR lpPluginID, IEIMPluginNotifyProc* pNotifyProc) = 0;

	virtual void RemovePluginNotifyProc(LPCTSTR lpPluginID) = 0;
};

// EIM为插件提供的基础服务接口
struct IEIMBaseService 
{

	struct ContactBriefInfo
	{
		TCHAR szContactID[EIM_CONTACT_ID_MAX_LEN];
		TCHAR szContactName[EIM_CONTACT_NAME_MAX_LEN];
		long lContactIcon;
	};

	virtual void GetAppVersion(int& major, int& minor, int& modify, int& build) = 0;

	virtual void GetCompanyName(CString& strCompanyName) = 0;

	virtual const CString& GetCurrentUserID() = 0;

	virtual long GetCurrentUserStatus() = 0;

	virtual int GetCurrentUserName(TCHAR szName[], int nBufferLen) = 0;

	virtual BOOL SetCurrentUserStatus(long lStatus) = 0;

	virtual BOOL SetCurrentUserName(const TCHAR* szName) = 0;

	virtual void Logoff() = 0;

	virtual void Exit() = 0;

	virtual int GetTribeMemberCount(const CString& strTribeID) = 0;
	virtual int GetTribeMemberIDs(const CString& strTribeID, LPTSTR* ppMemberIDs) = 0;

	virtual int GetCurrentUserPath(TCHAR szBuffer[], int nBufferLen) = 0;

	virtual int GetContactName(const CString& strContactID, TCHAR szBuffer[], int nBufferLen) = 0;
	virtual int GetContactIconFile(const CString& strContactID, BOOL bOnline, TCHAR szBuffer[], int nBufferLen) = 0;
	virtual int GetContacts(std::vector<ContactBriefInfo*>& vecContacts) = 0;
	virtual void ReleaseContacts(std::vector<ContactBriefInfo*>& vecContacts) = 0;

	virtual void GetMainServiceIPPort(DWORD& dwServerIpAddr, unsigned short& usServerPort) = 0;
	virtual void GetFileServiceIPPort(DWORD& dwServerIpAddr, unsigned short& usServerPort) = 0;
	virtual void GetDataServiceIPPort(DWORD& dwServerIpAddr, unsigned short& usServerPort) = 0;
	virtual void GetPluginServiceIPPort(DWORD& dwServerIpAddr, unsigned short& usServerPort) = 0;

	
	// {{窗口管理
	// 设置新的互斥窗体，同时关闭先前的互斥窗体
	virtual void SetMutexWnd(HWND hWnd) = 0;

	// 返回当前的互斥窗体
	virtual HWND GetMutexWnd() = 0;

	// 添加自删除窗体
	virtual void AddAutoDeleteWnd(HWND hWnd) = 0;

	// 移除自删除窗体
	virtual void RemoveAutoDeleteWnd(HWND hWnd) = 0;

	// 查找唯一实例窗口
	virtual HWND FindUniqueWnd(LPCTSTR strWndName) = 0;

	// 添加唯一实例窗口
	virtual BOOL InsertUniqueWnd(LPCTSTR strWndName, HWND hWnd) = 0;

	// 并闭移除唯一实例窗口指针
	virtual BOOL ReleaseUniqueWnd(LPCTSTR strWndName) = 0;

	// 移除唯一实例窗口指针
	virtual BOOL RemoveUniqueWnd(LPCTSTR strWndName) = 0;

	// 获取合适的窗口位置。该窗口位置是附加到主窗口上的合适位置。
	virtual void GetAttachedWndPos(const CSize& sizeWnd, CPoint& point) = 0;

	// 调整窗口位置
	virtual void AdjustWindowPos(CWnd* pWnd, CWnd* pParentWnd = NULL, 
		PluginChildWndPosition emPos = Plugin_Child_Attach, BOOL bSameHeight = FALSE,
		BOOL bLeftPriority = FALSE) = 0;
	// }}窗口管理

	virtual void SetMainFrmMainToolBarItemText(UINT nPluginID, UINT nItemID, LPCTSTR strItemText) = 0;

	virtual void ShowSystemNotify(LPCTSTR szTitle, LPCTSTR szContent, 
		LPCTSTR szUrl, UINT nPluginID, UINT nParam) = 0;

	virtual INT_PTR ShowSelectContactDlg(HWND hWndParent, LPCTSTR strWndTitle, DWORD dwMask,
		LPCTSTR strDefContacts, LPCTSTR strDefTribes,
		LPTSTR* pstrContacts, LPTSTR* pstrTribes) = 0;

	virtual BOOL SaveCurrentUserOption(LPCTSTR strSection, LPCTSTR strKey, LPCTSTR strValue) = 0;
	virtual BOOL LoadCurrentUserOption(LPCTSTR strSection, LPCTSTR strKey, TCHAR szBuffer[], int nBufferLen) = 0;
};

// EIM为插件提供的消息服务接口
struct IEIMMessageService
{
	virtual BOOL OpenChatDlg(const CString& strContactID, BOOL bActive) = 0;

	virtual void CloseChatDlg(const CString& strContactID) = 0;

	virtual BOOL OpenTribeDlg(const CString& strTribeID, BOOL bActive) = 0;

	virtual void CloseTribeDlg(const CString& strTribeID) = 0;

	virtual BOOL OpenGroupSendDlg(const CString& strContactIDs, const TCHAR* szMsg) = 0;

	virtual BOOL SendMsg(const CString& strContactID, const TCHAR* szMsg) = 0;

	virtual BOOL InputMsg(const CString& strContactID, const TCHAR* szMsg) = 0;

	virtual BOOL SendTribeMsg(const CString& strTribeID, const TCHAR* szMsg) = 0;

	virtual BOOL InputTribeMsg(const CString& strTribeID, const TCHAR* szMsg) = 0;

	virtual BOOL SendGroupMsg(LPCTSTR lpContactIDs, const TCHAR* szMsg) = 0;

	virtual BOOL SendAutoReplayMsg(const CString& strContactID, const TCHAR* szMsg) = 0;

	virtual BOOL OpenSmsDlg(const TCHAR* szMobileNum) = 0;

	virtual BOOL SendSms(const TCHAR* szMobileNum, const TCHAR* szSms) = 0;

	virtual BOOL GroupSendSms(TCHAR szMobileNums[][16], const TCHAR* szSms) = 0;

	virtual BOOL InsertSysMsg2ChatDlg(const CString& strContactID, LPCTSTR lpSender, LPCTSTR lpMsg) = 0;

	virtual BOOL InsertSysMsg2TribeDlg(const CString& strTribeID, LPCTSTR lpSender, LPCTSTR lpMsg) = 0;

	virtual BOOL SendPluginNormalNotify(const CString& strContactID, LPCTSTR lpPluginID, LPCTSTR lpPluginName, LPCTSTR lpMsg) = 0;

	virtual BOOL SendPluginTribeNotify(const CString& strTribeID, LPCTSTR lpPluginID, LPCTSTR lpPluginName, LPCTSTR lpMsg) = 0;

	virtual BOOL SendPluginGroupNotify(LPCTSTR lpContactIDs, LPCTSTR lpPluginID, LPCTSTR lpPluginName, LPCTSTR lpMsg) = 0;

};

// 插件处理基本业务的接口
struct IEIMPluginBaseProc
{
	virtual BOOL OnWindowsMessage(UINT nMsg, WPARAM wParam, LPARAM lParam, const CString& strIDContactOrTribe, BOOL bIsTribe) = 0;

	virtual BOOL OnCurrentUserStatusChanged(IMUserStatus emUserStatus) = 0;
	
	virtual BOOL OnCurrentUserLogon(IMUserStatus emUserStatus) = 0;
	
	virtual BOOL OnCurrentUserLogoff() = 0;

	virtual BOOL OnContactStatusChanged(const CString& strContactID, IMUserStatus emUserStatus) = 0;

	virtual BOOL OnAppExit() = 0;
};

// 插件处理消息的接口
struct IEIMPluginMessageProc
{
	virtual BOOL OnNewMsg(const CString& strContactID, long lMsgType, TCHAR* szMsg) = 0;

	virtual BOOL OnNewTribeMsg(const CString& strTribeID, TCHAR* szMsg) = 0;

	virtual BOOL OnSendMsg(const CString& strContactID, long lMsgType, TCHAR* szMsg) = 0;

	virtual BOOL OnSendTribeMsg(const CString& strTribeID, TCHAR* szMsg) = 0;

	virtual BOOL OnNewSms(const TCHAR* szMobileNum, TCHAR* szSms) = 0;

	virtual BOOL OnSendSms(const TCHAR* szMobileNum, TCHAR* szSms) = 0;

	virtual BOOL OnNewSysMsg(const DATE* dtMsgTime, const TCHAR* szTitle, const TCHAR* szContent) = 0;

	virtual BOOL OnNewEmailNotify(const DATE* dtMsgTime, const TCHAR* szSender, const TCHAR* szSubject, const TCHAR* szContent, UINT nNewMailCount) = 0;
};

// 插件内部消息处理接口
struct IEIMPluginNotifyProc
{
	virtual BOOL OnRecvNormalMsg(const DATE& dtTime, const CString& strSenderID, LPCTSTR lpMsg, BOOL bOfflineMsg) = 0;

	virtual BOOL OnRecvTribeMsg(const DATE& dtTime, const CString& strSenderID, const CString& strTribeID, LPCTSTR lpMsg, BOOL bOfflineMsg) = 0;
};


struct IEIMPluginClientSocket
{
	// 超时设置（milliseconds）
	virtual void SetTimeOut(DWORD dwConnectTimeOut, DWORD dwSendTimeOut, DWORD dwRecvTimeOut) = 0;

	// 连接。PORT为主机字节顺序
	virtual BOOL Connect(const CString& strIpAddr, unsigned short usPort) = 0;

	// 连接。IP、PORT均为主机字节顺序
	virtual BOOL Connect(DWORD dwIpAddr, unsigned short usPort) = 0;

	// 连接。strServerName为主机名称
	virtual BOOL ConnectByHostName(const CString& strServerName, unsigned short usPort) = 0;

	// 获取根据服务器名解析后的IP地址（网络顺序）
	virtual DWORD GetHostIpAddr() const = 0;

	// 断开
	virtual void Disconnect() = 0;

	// 发送数据
	virtual BOOL Send(LPBYTE pData, int nDataSize) = 0;

	// 接收一条完整的消息。该函数会分配buffer，通过pData传出，需要调用ReleaseMsg释放
	virtual BOOL RecvMsg(BYTE** ppData, int& nDataSize) = 0;

	virtual void ReleaseMsg(BYTE** ppData) = 0;

	// 获取最后一次错误
	virtual long GetLastError() = 0;
};


// API for plugins.
__declspec(dllexport) IEIMPluginManager* EIMGetPluginManager();
__declspec(dllexport) IEIMBaseService* EIMGetBaseService();
__declspec(dllexport) IEIMMessageService* EIMGetMessageService();
__declspec(dllexport) BOOL EIMCreatePluginClientSocket(LPCTSTR szPluginGUID, IEIMPluginClientSocket** ppClientSocket);
__declspec(dllexport) void EIMReleasePluginClientSocket(IEIMPluginClientSocket** ppClientSocket);

typedef BOOL (*PLUGININITIALIZE)(EIMPluginInfo& stPluginInfo);

typedef BOOL (*PLUGINUNINITIALIZE)();

typedef BOOL (*PLUGINREGISTERED)(LPCTSTR strCurrentPluginPath, UINT nPluginID);

#define PluginInitialize_Func_Name			_T("PluginInitialize")
#define PluginUninitialize_Func_Name		_T("PluginUninitialize")
#define PluginRegistered_Func_Name			_T("PluginRegistered")
