/*
"Last Seen mod" plugin for Miranda IM
Copyright ( C ) 2002-03  micron-x
Copyright ( C ) 2005-06  Y.B.

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.
*/

#include "stdafx.h"

static MWindowList hWindowList;

char* BuildSetting(int historyLast)
{
	static char setting[15];
	static char sztemp[15];
	*setting = '\0';
	mir_strcat(setting, "History_");
	mir_strcat(setting, _itoa(historyLast, sztemp, 10));
	return setting;
}

void HistoryWrite(MCONTACT hContact)
{
	int historyMax = g_plugin.getWord("HistoryMax", 10);
	if (historyMax < 0)
		historyMax = 0;
	else if (historyMax > 99)
		historyMax = 99;
	if (historyMax == 0)
		return;

	int historyFirst = g_plugin.getWord(hContact, "HistoryFirst", 0);
	if (historyFirst >= historyMax)
		historyFirst = 0;

	int historyLast = g_plugin.getWord(hContact, "HistoryLast", 0);
	if (historyLast >= historyMax)
		historyLast = historyMax - 1;

	ptrW str(g_plugin.getWStringA("HistoryStamp", DEFAULT_HISTORYSTAMP));
	g_plugin.setWString(hContact, BuildSetting(historyLast), ParseString(str, hContact));

	historyLast = (historyLast + 1) % historyMax;
	g_plugin.setWord(hContact, "HistoryLast", historyLast);
	if (historyLast == historyFirst)
		g_plugin.setWord(hContact, "HistoryFirst", (historyFirst + 1) % historyMax);
}

void LoadHistoryList(MCONTACT hContact, HWND hwnd, int nList)
{
	SendDlgItemMessage(hwnd, nList, LB_RESETCONTENT, 0, 0);
	int historyMax = g_plugin.getWord("HistoryMax", 10);
	if (historyMax < 0)
		historyMax = 0;
	else if (historyMax > 99)
		historyMax = 99;
	if (historyMax == 0)
		return;

	int historyFirst = g_plugin.getWord(hContact, "HistoryFirst", 0);
	if (historyFirst >= historyMax)
		historyFirst = 0;

	int historyLast = g_plugin.getWord(hContact, "HistoryLast", 0);
	if (historyLast >= historyMax)
		historyLast = historyMax - 1;

	for (int i = historyLast; i != historyFirst;) {
		i = (i - 1 + historyMax) % historyMax;

		DBVARIANT dbv;
		if (!g_plugin.getWString(hContact, BuildSetting(i), &dbv)) {
			SendDlgItemMessage(hwnd, nList, LB_ADDSTRING, 0, (LPARAM)dbv.pwszVal);
			db_free(&dbv);
		}
		else SendDlgItemMessage(hwnd, nList, LB_ADDSTRING, 0, (LPARAM)L"");
	}
}


HDWP MyResizeWindow(HDWP hDwp, HWND hwndDlg, HWND hwndControl,
	int nHorizontalOffset, int nVerticalOffset,
	int nWidthOffset, int nHeightOffset)
{
	POINT pt;
	RECT rcinit;

	if (nullptr == hwndDlg) /* Wine fix. */
		return hDwp;
	// get current bounding rectangle
	GetWindowRect(hwndControl, &rcinit);

	// get current top left point
	pt.x = rcinit.left;
	pt.y = rcinit.top;
	ScreenToClient(hwndDlg, &pt);

	// resize control
	return DeferWindowPos(hDwp, hwndControl, nullptr,
		pt.x + nHorizontalOffset,
		pt.y + nVerticalOffset,
		rcinit.right - rcinit.left + nWidthOffset,
		rcinit.bottom - rcinit.top + nHeightOffset,
		SWP_NOZORDER);


}

HDWP MyHorizCenterWindow(HDWP hDwp, HWND hwndDlg, HWND hwndControl,
	int nClientWidth, int nVerticalOffset,
	int nHeightOffset)
{
	POINT pt;
	RECT rcinit;

	if (nullptr == hwndDlg) /* Wine fix. */
		return hDwp;
	// get current bounding rectangle
	GetWindowRect(hwndControl, &rcinit);

	// get current top left point
	pt.x = rcinit.left;
	pt.y = rcinit.top;
	ScreenToClient(hwndDlg, &pt);

	// resize control
	return DeferWindowPos(hDwp, hwndControl, nullptr,
		(int)((nClientWidth - (rcinit.right - rcinit.left)) / 2),
		pt.y + nVerticalOffset,
		rcinit.right - rcinit.left,
		rcinit.bottom - rcinit.top + nHeightOffset,
		SWP_NOZORDER);

}

void MyResizeGetOffset(HWND hwndControl, int nWidth, int nHeight, int* nDx, int* nDy)
{
	RECT rcinit;

	// get current bounding rectangle
	GetWindowRect(hwndControl, &rcinit);

	// calculate offsets
	*nDx = nWidth - (rcinit.right - rcinit.left);
	*nDy = nHeight - (rcinit.bottom - rcinit.top);
}

INT_PTR CALLBACK HistoryDlgProc(HWND hwndDlg, UINT Message, WPARAM wparam, LPARAM lparam)
{
	MCONTACT hContact;
	wchar_t sztemp[1024];

	switch (Message) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		hContact = (MCONTACT)lparam;
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lparam);
		mir_snwprintf(sztemp, L"%s: %s", Clist_GetContactDisplayName(hContact), TranslateT("last seen history"));
		SetWindowText(hwndDlg, sztemp);
		Window_SetSkinIcon_IcoLib(hwndDlg, SKINICON_OTHER_MIRANDA);

		if (g_plugin.getByte(hContact, "OnlineAlert"))
			CheckDlgButton(hwndDlg, IDC_STATUSCHANGE, BST_CHECKED);

		SendDlgItemMessage(hwndDlg, IDC_DETAILS, BM_SETIMAGE, IMAGE_ICON, (WPARAM)Skin_LoadIcon(SKINICON_OTHER_USERDETAILS));
		SendDlgItemMessage(hwndDlg, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (WPARAM)Skin_LoadIcon(SKINICON_OTHER_DOWNARROW));
		SendDlgItemMessage(hwndDlg, IDC_SENDMSG, BM_SETIMAGE, IMAGE_ICON, (WPARAM)Skin_LoadIcon(SKINICON_EVENT_MESSAGE));

		//set-up tooltips
		SendDlgItemMessage(hwndDlg, IDC_DETAILS, BUTTONADDTOOLTIP, (WPARAM)TranslateT("View User's Details"), BATF_UNICODE);
		SendDlgItemMessage(hwndDlg, IDC_USERMENU, BUTTONADDTOOLTIP, (WPARAM)TranslateT("User Menu"), BATF_UNICODE);
		SendDlgItemMessage(hwndDlg, IDC_SENDMSG, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Send Instant Message"), BATF_UNICODE);

		Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, MODULENAME, "History_");
		ShowWindow(hwndDlg, SW_SHOW);
		return TRUE;

	case WM_MEASUREITEM:
		return Menu_MeasureItem(lparam);

	case WM_DRAWITEM:
		return Menu_DrawItem(lparam);

	case WM_COMMAND:
		hContact = (MCONTACT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
		if (Clist_MenuProcessCommand(LOWORD(wparam), MPCF_CONTACTMENU, hContact))
			break;

		switch (LOWORD(wparam)) {
		case IDCANCEL:
			SendMessage(hwndDlg, WM_CLOSE, 0, 0);
			break;
		case IDOK:
			if (IsDlgButtonChecked(hwndDlg, IDC_STATUSCHANGE) == BST_CHECKED)
				g_plugin.setByte(hContact, "OnlineAlert", 1);
			else
				g_plugin.setByte(hContact, "OnlineAlert", 0);
			SendMessage(hwndDlg, WM_CLOSE, 0, 0);
			break;
		case IDC_USERMENU:
			{
				RECT rc;
				GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc);
				HMENU hMenu = Menu_BuildContactMenu(hContact);
				TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, nullptr);
				DestroyMenu(hMenu);
			}
			break;
		case IDC_DETAILS:
			CallService(MS_USERINFO_SHOWDIALOG, hContact, 0);
			break;
		case IDC_SENDMSG:
			CallService(MS_MSG_SENDMESSAGE, hContact, 0);
			break;
		case IDC_TEST:
			debug(ParseString(LPGENW("Date: %d.%m.%y(%Y) \n Date desc: %W - %w - %E - %e \n Time: %H:%M:%S (%h-%p) \n user: %n - %u \n Status: %s \n IP: %i - %r"), hContact));
			break;
		}
		break;

	case WM_SIZE:
		int dx, dy;
		{
			HDWP hDwp = BeginDeferWindowPos(6);
			MyResizeGetOffset(GetDlgItem(hwndDlg, IDC_HISTORYLIST), LOWORD(lparam) - 15, HIWORD(lparam) - 99, &dx, &dy);
			hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_USERMENU), dx, 0, 0, 0);
			hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_DETAILS), dx, 0, 0, 0);
			hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_SENDMSG), dx, 0, 0, 0);
			hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_HISTORYLIST), 0, 0, dx, dy);
			hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_STATUSCHANGE), 0, dy, dx, 0);
			hDwp = MyHorizCenterWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDOK), LOWORD(lparam), dy, 0);
			EndDeferWindowPos(hDwp);
		}
		break;

	case WM_GETMINMAXINFO:
		MINMAXINFO mmi;
		{
			memcpy(&mmi, (LPMINMAXINFO)lparam, sizeof(MINMAXINFO));

			/* The minimum width in points*/
			mmi.ptMinTrackSize.x = 200;
			/* The minimum height in points*/
			mmi.ptMinTrackSize.y = 190;

			memcpy((LPMINMAXINFO)lparam, &mmi, sizeof(MINMAXINFO));
		}
		break;

	case WM_CLOSE:
		DestroyWindow(hwndDlg);
		WindowList_Remove(hWindowList, hwndDlg);
		break;

	case WM_DESTROY:
		Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, "History_");
		DestroyIcon((HICON)SendMessage(hwndDlg, WM_GETICON, ICON_BIG, 0));
		DestroyIcon((HICON)SendMessage(hwndDlg, WM_GETICON, ICON_SMALL, 0));
		break;
	}
	return FALSE;
}

void ShowHistory(MCONTACT hContact, uint8_t isAlert)
{
	HWND hHistoryDlg = WindowList_Find(hWindowList, hContact);
	if (hHistoryDlg == nullptr) {
		hHistoryDlg = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_HISTORY), nullptr, HistoryDlgProc, hContact);
		LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
		WindowList_Add(hWindowList, hHistoryDlg, hContact);
	}
	else {
		SetForegroundWindow(hHistoryDlg);
		LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
		SetFocus(hHistoryDlg);
	}

	if (isAlert)
		Skin_PlaySound("LastSeenTrackedStatusChange");
}

void InitHistoryDialog(void)
{
	hWindowList = WindowList_Create();
}

void UninitHistoryDialog(void)
{
	WindowList_Destroy(hWindowList);
}