// 30 may 2015
#include "uipriv_windows.hpp"

// TODO refine error handling

// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx
#define tabMargin 7

static void tabPageMargins(struct tabPage *tp, int *mx, int *my)
{
	uiWindowsSizing sizing;

	*mx = 0;
	*my = 0;
	if (!tp->margined)
		return;
	uiWindowsGetSizing(tp->hwnd, &sizing);
	*mx = tabMargin;
	*my = tabMargin;
	uiWindowsSizingDlgUnitsToPixels(&sizing, mx, my);
}

static void tabPageRelayout(struct tabPage *tp)
{
	RECT r;
	int mx, my;
	HWND child;

	if (tp->child == NULL)
		return;
	uiWindowsEnsureGetClientRect(tp->hwnd, &r);
	tabPageMargins(tp, &mx, &my);
	r.left += mx;
	r.top += my;
	r.right -= mx;
	r.bottom -= my;
	child = (HWND) uiControlHandle(tp->child);
	uiWindowsEnsureMoveWindowDuringResize(child, r.left, r.top, r.right - r.left, r.bottom - r.top);
}

// dummy dialog procedure; see below for details
// let's handle parent messages here to avoid needing to subclass
// TODO do we need to handle DM_GETDEFID/DM_SETDEFID here too because of the ES_WANTRETURN stuff at http://blogs.msdn.com/b/oldnewthing/archive/2007/08/20/4470527.aspx? what about multiple default buttons (TODO)?
// TODO we definitely need to do something about edit message handling; it does a fake close of our parent on pressing escape, causing uiWindow to stop responding to maximizes but still respond to events and then die horribly on destruction
static INT_PTR CALLBACK dlgproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	struct tabPage *tp;
	LRESULT lResult;

	if (uMsg == WM_INITDIALOG) {
		tp = (struct tabPage *) lParam;
		tp->hwnd = hwnd;
		SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR) tp);
		return TRUE;
	}
	if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) {
		SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONG_PTR) lResult);
		return TRUE;
	}
	if (uMsg == WM_WINDOWPOSCHANGED) {
		tp = (struct tabPage *) GetWindowLongPtrW(hwnd, DWLP_USER);
		tabPageRelayout(tp);
		// pretend the dialog hasn't handled this just in case the system needs to do something special
		return FALSE;
	}

	return FALSE;
}

// because Windows doesn't really support resources in static libraries, we have to embed this directly; oh well
/*
// this is the dialog template used by tab pages; see windows/tabpage.c for details
rcTabPageDialog DIALOGEX 0, 0, 100, 100
STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE
EXSTYLE WS_EX_CONTROLPARENT
BEGIN
	// nothing
END
*/
static const uint8_t data_rcTabPageDialog[] = {
	0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x50,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00,
	0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static_assert(ARRAYSIZE(data_rcTabPageDialog) == 32, "wrong size for resource rcTabPageDialog");

struct tabPage *newTabPage(uiControl *child)
{
	struct tabPage *tp;
	HRESULT hr;

	tp = uiprivNew(struct tabPage);

	// unfortunately this needs to be a proper dialog for EnableThemeDialogTexture() to work; CreateWindowExW() won't suffice
	if (CreateDialogIndirectParamW(hInstance, (const DLGTEMPLATE *) data_rcTabPageDialog,
		utilWindow, dlgproc, (LPARAM) tp) == NULL)
		logLastError(L"error creating tab page");

	tp->child = child;
	if (tp->child != NULL) {
		uiWindowsEnsureSetParentHWND((HWND) uiControlHandle(tp->child), tp->hwnd);
		uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl(tp->child));
	}

	hr = EnableThemeDialogTexture(tp->hwnd, ETDT_ENABLE | ETDT_USETABTEXTURE | ETDT_ENABLETAB);
	if (hr != S_OK)
		logHRESULT(L"error setting tab page background", hr);
		// continue anyway; it'll look wrong but eh

	// and start the tab page hidden
	ShowWindow(tp->hwnd, SW_HIDE);

	return tp;
}

void tabPageDestroy(struct tabPage *tp)
{
	// don't destroy the child with the page
	if (tp->child != NULL)
		uiWindowsControlSetParentHWND(uiWindowsControl(tp->child), NULL);
	// don't call EndDialog(); that's for the DialogBox() family of functions instead of CreateDialog()
	uiWindowsEnsureDestroyWindow(tp->hwnd);
	uiprivFree(tp);
}

void tabPageMinimumSize(struct tabPage *tp, int *width, int *height)
{
	int mx, my;

	*width = 0;
	*height = 0;
	if (tp->child != NULL)
		uiWindowsControlMinimumSize(uiWindowsControl(tp->child), width, height);
	tabPageMargins(tp, &mx, &my);
	*width += 2 * mx;
	*height += 2 * my;
}
