/*
"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 = db_get_w(NULL, S_MOD, "HistoryMax", 10);
	if (historyMax < 0)
		historyMax = 0;
	else if (historyMax > 99)
		historyMax = 99;
	if (historyMax == 0)
		return;

	int historyFirst = db_get_w(hContact, S_MOD, "HistoryFirst", 0);
	if (historyFirst >= historyMax)
		historyFirst = 0;

	int historyLast = db_get_w(hContact, S_MOD, "HistoryLast", 0);
	if (historyLast >= historyMax)
		historyLast = historyMax - 1;

	TCHAR *ptszString;
	DBVARIANT dbv;
	if (!db_get_ts(NULL, S_MOD, "HistoryStamp", &dbv)) {
		ptszString = ParseString(dbv.ptszVal, hContact, 0);
		db_free(&dbv);
	}
	else ptszString = ParseString(DEFAULT_HISTORYSTAMP, hContact, 0);
	db_set_ts(hContact, S_MOD, BuildSetting(historyLast), ptszString);

	historyLast = (historyLast + 1) % historyMax;
	db_set_w(hContact, S_MOD, "HistoryLast", historyLast);
	if (historyLast == historyFirst)
		db_set_w(hContact, S_MOD, "HistoryFirst", (historyFirst + 1) % historyMax);
}

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

	int historyFirst = db_get_w(hContact, S_MOD, "HistoryFirst", 0);
	if (historyFirst >= historyMax)
		historyFirst = 0;

	int historyLast = db_get_w(hContact, S_MOD, "HistoryLast", 0);
	if (historyLast >= historyMax)
		historyLast = historyMax - 1;

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

		DBVARIANT dbv;
		if (!db_get_ts(hContact, S_MOD, BuildSetting(i), &dbv)) {
			SendDlgItemMessage(hwnd, nList, LB_ADDSTRING, 0, (LPARAM)dbv.ptszVal);
			db_free(&dbv);
		}
		else SendDlgItemMessage(hwnd, nList, LB_ADDSTRING, 0, (LPARAM)_T(""));
	}
}


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

	if (NULL == 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, NULL,
		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 (NULL == 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, NULL,
		(int)((nClientWidth - (rcinit.right - rcinit.left)) / 2),
		pt.y + nVerticalOffset,
		rcinit.right - rcinit.left,
		rcinit.bottom - rcinit.top + nHeightOffset,
		SWP_NOZORDER);

}

void MyResizeGetOffset(HWND hwndDlg, 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;
	TCHAR sztemp[1024];

	switch (Message) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		hContact = (MCONTACT)lparam;
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lparam);
		mir_sntprintf(sztemp, _countof(sztemp), _T("%s: %s"),
			pcli->pfnGetContactDisplayName(hContact, 0),
			TranslateT("last seen history"));
		SetWindowText(hwndDlg, sztemp);
		SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_MIRANDA));
		SendMessage(hwndDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_MIRANDA));

		if (db_get_b(hContact, S_MOD, "OnlineAlert", 0))
			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_TCHAR);
		SendDlgItemMessage(hwndDlg, IDC_USERMENU, BUTTONADDTOOLTIP, (WPARAM)TranslateT("User Menu"), BATF_TCHAR);
		SendDlgItemMessage(hwndDlg, IDC_SENDMSG, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Send Instant Message"), BATF_TCHAR);

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

	case WM_MEASUREITEM:
		return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lparam);

	case WM_DRAWITEM:
		return Menu_DrawItem((LPDRAWITEMSTRUCT)lparam);

	case WM_COMMAND:
		hContact = (MCONTACT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
		if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(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)
				db_set_b(hContact, S_MOD, "OnlineAlert", 1);
			else
				db_set_b(hContact, S_MOD, "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, NULL);
				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(LPGENT("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, 0));
			break;
		}
		break;

	case WM_SIZE:
		int dx, dy;
		{
			HDWP hDwp = BeginDeferWindowPos(6);
			MyResizeGetOffset(hwndDlg, 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, S_MOD, "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, BYTE isAlert)
{
	HWND hHistoryDlg = WindowList_Find(hWindowList, hContact);
	if (hHistoryDlg == NULL) {
		hHistoryDlg = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_HISTORY), NULL, HistoryDlgProc, hContact);
		LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
		WindowList_Add(hWindowList, hHistoryDlg, hContact);
	}
	else {
		SetForegroundWindow(hHistoryDlg);
		LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
		SetFocus(hHistoryDlg);
	}

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

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

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