/*
Miranda Crash Dumper Plugin
Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved

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 version 2
of the License.

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, see <http://www.gnu.org/licenses/>.
*/

#include "utils.h"

HWND hViewWnd;
extern HINSTANCE hInst;


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

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

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

	return DeferWindowPos(hDwp, hwndCtrl, NULL,
		pt.x + nHorizontalOffset, 
		pt.y + nVerticalOffset,
		rcinit.right - rcinit.left + nWidthOffset, 
		rcinit.bottom - rcinit.top + nHeightOffset,
		SWP_NOZORDER);
}

BOOL MyResizeGetOffset(HWND hwndCtrl, int nWidth, int nHeight, int* nDx, int* nDy) 
{
	RECT rcinit;

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

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

	return rcinit.bottom != rcinit.top && nHeight > 0;
}

INT_PTR CALLBACK DlgProcView(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 
{
	switch (msg) 
	{
	case WM_INITDIALOG:
		if (hViewWnd == NULL)
		{
			hViewWnd = hwndDlg;
			TranslateDialogDefault(hwndDlg);
			SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx(IDI_VI, true));
			SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx(IDI_VI));

			CHARFORMAT2 chf;
			chf.cbSize = sizeof(chf);
			SendDlgItemMessage(hwndDlg, IDC_VIEWVERSIONINFO, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&chf);
			_tcscpy(chf.szFaceName, TEXT("Courier New"));
			SendDlgItemMessage(hwndDlg, IDC_VIEWVERSIONINFO, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&chf);

			bkstring buffer;
			buffer.reserve(0x1800);
			PrintVersionInfo(buffer, (unsigned int)lParam);
			SetDlgItemText(hwndDlg, IDC_VIEWVERSIONINFO, buffer.c_str());
			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);

			if(lParam & VI_FLAG_PRNDLL)
			{
				SetWindowText(hwndDlg,TranslateT("View Version Information (with DLLs)"));
			}

			Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, PluginName, "ViewInfo_");
			ShowWindow(hwndDlg, SW_SHOW);
		}
		else
			DestroyWindow(hwndDlg);
		break;

	case WM_SIZE: 
		{
			int dx, dy, bsz;
			HDWP hDwp;
			RECT rc;

			GetWindowRect(GetDlgItem(hwndDlg, IDC_FILEVER), &rc);
			bsz = rc.bottom - rc.top;

			if (MyResizeGetOffset(GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO), 
				LOWORD(lParam)-20, HIWORD(lParam)-30-bsz, &dx, &dy))
			{
				hDwp = BeginDeferWindowPos(4);
				hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_FILEVER), 0, dy, 0, 0);
				hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_CLIPVER), dx/2, dy, 0, 0);
				hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDCANCEL), dx, dy, 0, 0);
				hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO), 0, 0, dx, dy);
				EndDeferWindowPos(hDwp);
			}
		}				
		break;

	case WM_GETMINMAXINFO: 
		{
			LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;

			// The minimum width in points
			mmi->ptMinTrackSize.x = 350;
			// The minimum height in points
			mmi->ptMinTrackSize.y = 300;
		}
		break;

	case WM_COMMAND:
		switch(LOWORD(wParam)) 
		{
		case IDC_CLIPVER:
			CallService(MS_CRASHDUMPER_STORETOCLIP, 0, GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
			break;

		case IDC_FILEVER:
			CallService(MS_CRASHDUMPER_STORETOFILE, 0, GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
			break;

		case IDCANCEL:
			DestroyWindow(hwndDlg);
			break;
		}
		break;

	case WM_CONTEXTMENU:
		{
			HWND hView = GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO);
			RECT rc;
			GetWindowRect(hView, &rc);

			POINT pt;
			pt.x = LOWORD(lParam); 
			pt.y = HIWORD(lParam); 
			if (PtInRect(&rc, pt))
			{
				static const CHARRANGE all = { 0, -1 };

				HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT));
				HMENU hSubMenu = GetSubMenu(hMenu, 0);
				TranslateMenu(hSubMenu);

				CHARRANGE sel; 
				SendMessage(hView, EM_EXGETSEL, 0, (LPARAM)&sel);
				if (sel.cpMin == sel.cpMax)
					EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);

				switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) 
				{
				case IDM_COPY:
					SendMessage(hView, WM_COPY, 0, 0);
					break;

				case IDM_COPYALL:
					SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&all);
					SendMessage(hView, WM_COPY, 0, 0);
					SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&sel);
					break;

				case IDM_SELECTALL:
					SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&all);
					break;
				}
				DestroyMenu(hMenu);
			}
		}
		break;

	case WM_DESTROY: 
		hViewWnd = NULL;
		Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
		Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
		Utils_SaveWindowPosition(hwndDlg, NULL, PluginName, "ViewInfo_");
		if (servicemode) PostQuitMessage(0); 
		break;
	}
	return FALSE;
}


void DestroyAllWindows(void)
{
	if (hViewWnd != NULL) DestroyWindow(hViewWnd);
	hViewWnd = NULL;
}


INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 
{
	switch (msg) 
	{
	case WM_INITDIALOG:
		{
			TranslateDialogDefault(hwndDlg);

			DBVARIANT dbv;
			if (db_get_s(NULL, PluginName, "Username", &dbv) == 0)
			{
				SetDlgItemTextA(hwndDlg, IDC_USERNAME, dbv.pszVal);
				db_free(&dbv);
			}
			if (db_get_s(NULL, PluginName, "Password", &dbv) == 0)
			{
				CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal);
				SetDlgItemTextA(hwndDlg, IDC_PASSWORD, dbv.pszVal);
				db_free(&dbv);
			}
			CheckDlgButton(hwndDlg, IDC_UPLOADCHN, db_get_b(NULL, PluginName, "UploadChanged", 0));
			CheckDlgButton(hwndDlg, IDC_CLASSICDATES, clsdates);
			CheckDlgButton(hwndDlg, IDC_DATESUBFOLDER, dtsubfldr);
		}
		break;

	case WM_COMMAND:
		if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) 
			SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
		break;

	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->code == (unsigned)PSN_APPLY)
		{
			char szSetting[100];
			GetDlgItemTextA(hwndDlg, IDC_USERNAME, szSetting, SIZEOF(szSetting));
			db_set_s(NULL, PluginName, "Username", szSetting);

			GetDlgItemTextA(hwndDlg, IDC_PASSWORD, szSetting, SIZEOF(szSetting));
			CallService(MS_DB_CRYPT_ENCODESTRING, SIZEOF(szSetting), (LPARAM)szSetting);
			db_set_s(NULL, PluginName, "Password", szSetting);

			db_set_b(NULL, PluginName, "UploadChanged", 
				(BYTE)IsDlgButtonChecked(hwndDlg, IDC_UPLOADCHN));

			clsdates = IsDlgButtonChecked(hwndDlg, IDC_CLASSICDATES) == BST_CHECKED;
			if (clsdates)
				db_set_b(NULL, PluginName, "ClassicDates", 1);
			else
				db_unset(NULL, PluginName, "ClassicDates");
			dtsubfldr = IsDlgButtonChecked(hwndDlg, IDC_DATESUBFOLDER) == BST_CHECKED;
			if (dtsubfldr)
				db_set_b(NULL, PluginName, "SubFolders", 1);
			else
				db_unset(NULL, PluginName, "SubFolders");
		}
		break;
	}
	return FALSE;
}


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

	case WM_COMMAND:
		switch ((int)PUGetPluginData(hWnd)) {
		case 0:
			OpenAuthUrl("http://www.miranda-vi.org/");
			break;

		case 1:
			OpenAuthUrl("http://%s.miranda-vi.org/global");
			break;

		case 3:
			TCHAR path[MAX_PATH];
			crs_sntprintf(path, MAX_PATH, TEXT("%s\\VersionInfo.txt"), VersionInfoFolder);
			ShellExecute(NULL, TEXT("open"), path, NULL, NULL, SW_SHOW);
			break;

		}
		PUDeletePopup(hWnd);
		break;

	case UM_FREEPLUGINDATA:
		Skin_ReleaseIcon((HICON)SendMessage(hWnd, WM_SETICON, ICON_BIG, 0));
		Skin_ReleaseIcon((HICON)SendMessage(hWnd, WM_SETICON, ICON_SMALL, 0));
		break;
	}

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

void ShowMessage(int type, const TCHAR* format, ...)
{
	POPUPDATAT pi = {0};

	va_list va;
	va_start(va, format);
	int len = _vsntprintf(pi.lptzText, SIZEOF(pi.lptzText)-1, format, va);
	pi.lptzText[len] = 0;
	va_end(va);

	if (ServiceExists(MS_POPUP_ADDPOPUPT))
	{
		_tcscpy(pi.lptzContactName, TEXT(PluginName));
		pi.lchIcon = LoadIconEx(IDI_VI);
		pi.PluginWindowProc = DlgProcPopup;
		pi.PluginData = (void*)type;

		PUAddPopupT(&pi);
	}
	else
		MessageBox(NULL, pi.lptzText, TEXT(PluginName), MB_OK | MB_ICONINFORMATION);
}