#include "StdAfx.h"
#include "sametime.h"


LRESULT CALLBACK PopupWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
	case WM_COMMAND:
		PUDeletePopup(hWnd);
		break;

	case WM_CONTEXTMENU:
		PUDeletePopup(hWnd);
		break;

	case UM_FREEPLUGINDATA:
		PopupData* puData = (PopupData*)PUGetPluginData(hWnd);
		if (puData != NULL && puData != (PopupData*)CALLSERVICE_NOTFOUND) {
			mir_free(puData->title);
			mir_free(puData->text);
			mir_free(puData);
		}
		break;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}


void CSametimeProto::RegisterPopups()
{
	TCHAR szDescr[256];
	char szName[256];

	debugLog(_T("CSametimeProto::RegisterPopups()"));

	POPUPCLASS puc = { sizeof(puc) };
	puc.PluginWindowProc = PopupWindowProc;
	puc.flags = PCF_TCHAR;
	puc.ptszDescription = szDescr;
	puc.pszName = szName;

	mir_snprintf(szName, SIZEOF(szName), "%s_%s", m_szModuleName, "Notify");
	mir_sntprintf(szDescr, SIZEOF(szDescr), _T("%s/%s"), m_tszUserName, TranslateT("Notification"));
	puc.hIcon = CopyIcon(LoadIconEx("notify", FALSE));
	ReleaseIconEx("notify", FALSE);
	puc.iSeconds = 8;
	puc.colorBack = GetSysColor(COLOR_BTNFACE);
	puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
	hPopupNotify = Popup_RegisterClass(&puc);

	mir_snprintf(szName, SIZEOF(szName), "%s_%s", m_szModuleName, "Error");
	mir_sntprintf(szDescr, SIZEOF(szDescr), _T("%s/%s"), m_tszUserName, TranslateT("Error"));
	puc.hIcon = CopyIcon(LoadIconEx("error", FALSE));
	ReleaseIconEx("error", FALSE);
	puc.iSeconds = 10;
	puc.colorBack = GetSysColor(COLOR_BTNFACE);
	puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
	hPopupError = Popup_RegisterClass(&puc);
}


void CSametimeProto::UnregisterPopups()
{
	debugLog(_T("CSametimeProto::RegisterPopups()"));
	Popup_UnregisterClass(hPopupError);
	Popup_UnregisterClass(hPopupNotify);
}


void CALLBACK sttMainThreadCallback(PVOID dwParam)
{

	PopupData* puData = (PopupData*)dwParam;
	CSametimeProto* proto = puData->proto;

	ErrorDisplay disp = proto->options.err_method;
	// funny logic :) ... try to avoid message boxes
	// if want baloons but no balloons, try popups
	// if want popups but no popups, try baloons
	// if, after that, you want balloons but no balloons, revert to message boxes
	if (disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP;
	if (disp == ED_POP && !ServiceExists(MS_POPUP_ADDPOPUPCLASS)) disp = ED_BAL;
	if (disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB;

	if (disp == ED_POP) {
		POPUPDATACLASS ppd = { sizeof(ppd) };
		char szName[256];
		ppd.ptszTitle = puData->title;
		ppd.ptszText = puData->text;
		if (puData->flag == SAMETIME_POPUP_ERROR)
			mir_snprintf(szName, SIZEOF(szName), "%s_%s", proto->m_szModuleName, "Error");
		else
			mir_snprintf(szName, SIZEOF(szName), "%s_%s", proto->m_szModuleName, "Notify");
		ppd.pszClassName = szName;
		CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&ppd);
	}
	else if (disp == ED_BAL) {
		MIRANDASYSTRAYNOTIFY sn = { sizeof(sn) };
		sn.szProto = proto->m_szModuleName;
		sn.tszInfoTitle = puData->title;
		sn.tszInfo = puData->text;
		sn.dwInfoFlags = NIIF_INTERN_UNICODE;
		if (puData->flag == SAMETIME_POPUP_ERROR) {
			sn.dwInfoFlags = sn.dwInfoFlags | NIIF_WARNING;
			sn.uTimeout = 1000 * 10;
		}
		else {
			sn.dwInfoFlags = sn.dwInfoFlags | NIIF_INFO;
			sn.uTimeout = 1000 * 8;
		}
		CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn);
	}
	else { //disp == ED_MB
		if (puData->flag == SAMETIME_POPUP_ERROR)
			MessageBox(NULL, puData->text, puData->title, MB_OK | MB_ICONWARNING);
		else
			MessageBox(NULL, puData->text, puData->title, MB_OK | MB_ICONINFORMATION);
	}

	if (disp != ED_POP) {
		mir_free(puData->title);
		mir_free(puData->text);
		mir_free(puData);
	}
}

void CSametimeProto::showPopup(const TCHAR* msg, SametimePopupEnum flag)
{
	if (Miranda_Terminated()) return;

	PopupData *puData = (PopupData*)mir_calloc(sizeof(PopupData));
	puData->flag = flag;
	puData->title = mir_tstrdup(m_tszUserName);
	puData->text = mir_tstrdup(msg);
	puData->proto = this;

	CallFunctionAsync(sttMainThreadCallback, puData);
}

void CSametimeProto::showPopup(guint32 code)
{
	struct mwReturnCodeDesc *rcDesc = mwGetReturnCodeDesc(code);

	SametimePopupEnum flag = (rcDesc->type == mwReturnCodeError ? SAMETIME_POPUP_ERROR : SAMETIME_POPUP_INFO);
	TCHAR buff[512];
	mir_sntprintf(buff, SIZEOF(buff), TranslateT("%s\n\nSametime error %S\n%s"), TranslateTS(_A2T(rcDesc->name)), rcDesc->codeString, TranslateTS(_A2T(rcDesc->description)));

	showPopup(buff, flag);
	debugLog(buff);

	g_free(rcDesc->codeString);
	g_free(rcDesc->name);
	g_free(rcDesc->description);
	g_free(rcDesc);
}

void LogFromGLib(const gchar* log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data)
{
	CSametimeProto* proto = (CSametimeProto*)user_data;
	proto->debugLog(_A2T(message));
}

void CSametimeProto::RegisterGLibLogger()
{
	debugLog(_T("CSametimeProto::RegisterGLibLogger"));
	gLogHandler = g_log_set_handler(G_LOG_DOMAIN, G_LOG_LEVEL_MASK, LogFromGLib, this);
}

void CSametimeProto::UnRegisterGLibLogger()
{
	debugLog(_T("CSametimeProto::UnRegisterGLibLogger"));
	if (gLogHandler) g_log_remove_handler(G_LOG_DOMAIN, gLogHandler);
}