/*******************************************************************************
 * Copyright (c) 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/


#include "stdafx.h"
#include "ExplorerBar.h"

/* initialize constants */
const UINT ExplorerBar::ServerStateChangeMsg = RegisterWindowMessage(L"IECrossfireServerStateChanged");
const wchar_t* ExplorerBar::ServerWindowClass = L"_IECrossfireServer";
const wchar_t* ExplorerBar::WindowClass = L"_ExplorerBarMessageWindow";


ExplorerBar::ExplorerBar() {
	m_hWnd = m_hWndParent = 0;
	m_pSite = NULL;
	m_server = NULL;
	m_serverPort = 0;
	m_serverState = STATE_DISCONNECTED;

	HKEY key;
	LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\IBM\\IECrossfireServer", 0, KEY_QUERY_VALUE, &key);
	if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
		Logger::error("ExplorerBar ctor: RegOpenKeyEx() failed", result);
	} else {
		DWORD size = sizeof(unsigned int);
		result = RegQueryValueEx(key, L"LastPort", NULL, NULL, (LPBYTE)&m_serverPort, &size);
		if (result != ERROR_SUCCESS) {
			Logger::error("ExplorerBar ctor: RegQueryValueEx() failed", result);
		}
		RegCloseKey(key);
	}
	if (!m_serverPort) {
		m_serverPort = 5000;
	}

	/* create a message-only window to receive server state change notifications */
	HINSTANCE module = GetModuleHandle(NULL);
	WNDCLASS ex;
	ex.style = 0;
	ex.lpfnWndProc = WndProc;
	ex.cbClsExtra = 0;
	ex.cbWndExtra = 0;
	ex.hInstance = module;
	ex.hIcon = NULL;
	ex.hCursor = NULL;
	ex.hbrBackground = NULL;
	ex.lpszMenuName = NULL;
	ex.lpszClassName = WindowClass;
	RegisterClass(&ex);
	m_messageWindow = CreateWindow(WindowClass, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, module, NULL);
	if (!m_messageWindow) {
		Logger::error("ExplorerBar ctor(): failed to create message-only window", GetLastError());
	} else {
		SetWindowLongPtr(m_messageWindow, GWL_USERDATA, (__int3264)(LONG_PTR)this);
	}
}

ExplorerBar::~ExplorerBar() {
	if (m_server) {
		m_server->Release();
	}
	if (m_messageWindow) {
		DestroyWindow(m_messageWindow);
		UnregisterClass(WindowClass, GetModuleHandle(NULL));
	}
}


/* IClassFactory */

STDMETHODIMP ExplorerBar::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) {
	CComObject<ExplorerBar>* explorerBar = NULL;
	HRESULT hr = CComObject<ExplorerBar>::CreateInstance(&explorerBar);
	if (FAILED(hr)) {
		Logger::error("ExplorerBar.CreateInstance(): CreateInstance() failed", hr);
		return S_FALSE;
	}
	explorerBar->AddRef();
	hr = explorerBar->QueryInterface(riid, ppvObject);
	explorerBar->Release();
	return hr;
}

STDMETHODIMP ExplorerBar::LockServer(BOOL fLock) {
	return S_OK;
}

/* IObjectWithSite */

STDMETHODIMP ExplorerBar::SetSite(IUnknown *punkSite) {
	if (m_pSite) {
		m_pSite->Release();
		m_pSite = NULL;
	}
	if (punkSite) {
		initServer(false);
		IOleWindow *pOleWindow;
		m_hWndParent = NULL;
		if (SUCCEEDED(punkSite->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow))) {
			pOleWindow->GetWindow(&m_hWndParent);
			pOleWindow->Release();
		}
		if (!m_hWndParent) {
			return E_FAIL;
		}
		if (!createWindow()) {
			return E_FAIL;
		}
		if (FAILED(punkSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&m_pSite))) {
			return E_FAIL;
		}
	}
	return S_OK;
}

STDMETHODIMP ExplorerBar::GetSite(REFIID riid, LPVOID *ppvReturn) {
	*ppvReturn = NULL;
	if (m_pSite) {
		return m_pSite->QueryInterface(riid, ppvReturn);
	}
	return E_FAIL;
}

/* IPersistStream */

STDMETHODIMP ExplorerBar::GetClassID(CLSID *pClassID) {
	*pClassID = CLSID_ExplorerBar;
	return S_OK;
}

STDMETHODIMP ExplorerBar::IsDirty() {
	return S_FALSE;
}

STDMETHODIMP ExplorerBar::Load(IStream *pStm) {
	return S_OK;
}

STDMETHODIMP ExplorerBar::Save(IStream *pStm, BOOL fClearDirty) {
	return S_OK;
}

STDMETHODIMP ExplorerBar::GetSizeMax(ULARGE_INTEGER *pcbSize) {
	return E_NOTIMPL;
}

/* IDeskBand */

STDMETHODIMP ExplorerBar::GetWindow(HWND *phwnd) {
	*phwnd = m_hWnd;
	return S_OK;
}

STDMETHODIMP ExplorerBar::ContextSensitiveHelp(BOOL fEnterMode) {
	return E_NOTIMPL;
}

STDMETHODIMP ExplorerBar::ShowDW(BOOL fShow) {
	if (m_hWnd) {
		ShowWindow(m_hWnd, fShow ? SW_SHOW : SW_HIDE);
	}
    return S_OK;
}

STDMETHODIMP ExplorerBar::CloseDW(DWORD dwReserved) {
	ShowWindow(m_hWnd, SW_HIDE);
	if (IsWindow(m_hWnd)) {
		DestroyWindow(m_hWnd);
	}
	m_hWnd = NULL;
	return S_OK;
}

STDMETHODIMP ExplorerBar::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) {
	return E_NOTIMPL;
}

STDMETHODIMP ExplorerBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi) {
	if (pdbi) {
		if (pdbi->dwMask & DBIM_MINSIZE) {
			pdbi->ptMinSize.x = 0;
			pdbi->ptMinSize.y = 50;
		}

		if (pdbi->dwMask & DBIM_MAXSIZE) {
			pdbi->ptMaxSize.x = -1;
			pdbi->ptMaxSize.y = -1;
		}

		if (pdbi->dwMask & DBIM_INTEGRAL) {
			pdbi->ptIntegral.x = 1;
			pdbi->ptIntegral.y = 1;
		}

		if (pdbi->dwMask & DBIM_ACTUAL) {
			pdbi->ptMinSize.x = 0;
			pdbi->ptMinSize.y = 50;
		}

		if (pdbi->dwMask & DBIM_TITLE) {
			wchar_t* title = L"Crossfire";
			wcsncpy_s(pdbi->wszTitle, 256, title, wcslen(title));
        }

		if (pdbi->dwMask & DBIM_MODEFLAGS) {
			pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
		}

		if (pdbi->dwMask & DBIM_BKCOLOR) {
			pdbi->dwMask &= ~DBIM_BKCOLOR;
		}
		return S_OK;
	}

	return E_INVALIDARG;
}

/* IInputObject */

STDMETHODIMP ExplorerBar::UIActivateIO(BOOL fActivate, LPMSG pMsg) {
	if (fActivate) {
		SetFocus(m_hWnd);
	}
	return S_OK;
}

STDMETHODIMP ExplorerBar::HasFocusIO() {
	return m_bFocus ? S_OK : S_FALSE;
}

STDMETHODIMP ExplorerBar::TranslateAcceleratorIO(LPMSG pMsg) {
	return E_NOTIMPL;
}

/* ExplorerBar */

void ExplorerBar::createControls() {
	m_statusLabel = CreateWindowEx(
		0,
		WC_STATIC,
		NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_NOTIFY | SS_LEFTNOWORDWRAP,
		0, 0, 0, 0,
		m_hWnd,
		0,
		g_hInst,
		(LPVOID)this);

	m_separator = CreateWindowEx(
		0,
		WC_STATIC,
		NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_NOTIFY | SS_OWNERDRAW,
		0, 0, 0, 0,
		m_hWnd,
		0,
		g_hInst,
		(LPVOID)this);

	m_portLabel = CreateWindowEx(
		0,
		WC_STATIC,
		NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_NOTIFY | SS_LEFTNOWORDWRAP,
		0, 0, 0, 0,
		m_hWnd,
		0,
		g_hInst,
		(LPVOID)this);
	SetWindowText(m_portLabel, L"Port:");

	m_portText = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        WC_EDIT,
        NULL,
        WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_CLIPSIBLINGS | WS_TABSTOP | ES_NUMBER,
        0, 0, 0, 0,
        m_hWnd,
        0,
		g_hInst,
		(LPVOID)this);
	SendMessage(m_portText, EM_SETLIMITTEXT, 5, 0);

	m_portUpDown = CreateWindowEx(
        0,
		UPDOWN_CLASS,
        NULL,
        WS_CHILD | WS_VISIBLE | UDS_AUTOBUDDY | UDS_WRAP | UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_NOTHOUSANDS,
        0, 0, 0, 0,
        m_hWnd,
        0,
		g_hInst,
		(LPVOID)this);
	SendMessage(m_portUpDown, UDM_SETRANGE32, 1000, 65534);

	m_button = CreateWindowEx(
        0,
		WC_BUTTON,
        NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | BS_PUSHBUTTON | WS_TABSTOP,
        0, 0, 0, 0,
        m_hWnd,
        0,
		g_hInst,
		(LPVOID)this);

	m_errorLabel = CreateWindowEx(
		0,
		WC_STATIC,
		NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_NOTIFY | SS_LEFTNOWORDWRAP,
		0, 0, 0, 0,
		m_hWnd,
		0,
		g_hInst,
		(LPVOID)this);

	/*
	 * Calculate the size of the port text and cache it.  This is done
	 * because its preferred size does not change, and to provide a
	 * baseline for vertical centering of the other controls.
	 */
	HDC hDC = GetDC(m_portText);
	LRESULT newFont = SendMessage(m_portText, WM_GETFONT, 0, 0);
	HGDIOBJ oldFont = SelectObject(hDC, (HGDIOBJ)newFont);
	TEXTMETRICW tm;
	GetTextMetrics(hDC, &tm);
	LONG height = tm.tmHeight;
	RECT rect;
	DrawText(hDC, L"000000", 6, &rect, DT_CALCRECT | DT_EDITCONTROL | DT_NOPREFIX);
	LONG width = rect.right - rect.left;
	if (newFont != 0) {
		SelectObject(hDC, oldFont);
	}
	ReleaseDC(m_portText, hDC);

	/* Factor in the size of the text control's trim */
	SetRect(&rect, 0, 0, width, height);
	LONG style = GetWindowLong(m_portText, GWL_STYLE);
	LONG exStyle = GetWindowLong(m_portText, GWL_EXSTYLE);
	AdjustWindowRectEx(&rect, style, false, exStyle);
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;
	width += 2; height += 2;
	m_portTextSize.x = width;
	m_portTextSize.y = height;

	/* subclass the separator in order to owner-draw it */
//	SetWindowLongPtr(m_separator, GWL_USERDATA, (__int3264)(LONG_PTR)this);
//	staticProc = (WNDPROC)SetWindowLongPtr(m_separator, GWLP_WNDPROC, (__int3264)(LONG_PTR)WndProc);

//	Logger::error("handle: m_button", (int)m_button);
//	Logger::error("handle: m_errorLabel", (int)m_errorLabel);
//	Logger::error("handle: m_portLabel", (int)m_portLabel);
//	Logger::error("handle: m_portText", (int)m_portText);
//	Logger::error("handle: m_portUpDown", (int)m_portUpDown);
//	Logger::error("handle: m_separator", (int)m_separator);
//	Logger::error("handle: m_statusLabel", (int)m_statusLabel);
//	Logger::error("handle: m_hWnd", (int)m_hWnd);
//	Logger::error("handle: m_hWndParent", (int)m_hWndParent);
}

bool ExplorerBar::createWindow() {
	if (!m_hWnd) {
		if (!m_hWndParent) {
			return false;
		}

		LPCTSTR CLASSNAME = L"CrossfireExplorerBar";
		if (!GetClassInfo(g_hInst, CLASSNAME, &wc)) {
			ZeroMemory(&wc, sizeof(wc));
			wc.style = /*CS_HREDRAW | CS_VREDRAW |*/ CS_GLOBALCLASS;
			wc.lpfnWndProc = (WNDPROC)WndProc;
			wc.cbClsExtra = 0;
			wc.cbWndExtra = 0;
			wc.hInstance = g_hInst;
			wc.hIcon = NULL;
			wc.hCursor = LoadCursor(NULL, IDC_ARROW);
			wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
			wc.lpszMenuName = NULL;
			wc.lpszClassName = CLASSNAME;

			if (!RegisterClass(&wc)) {
				// If RegisterClass fails, CreateWindow below will fail.
			}
		}

		RECT rc;
		GetClientRect(m_hWndParent, &rc);

		CreateWindowEx(
			0,
			CLASSNAME,
			NULL,
			WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
			rc.left,
			rc.top,
			rc.right - rc.left,
			rc.bottom - rc.top,
			m_hWndParent,
			NULL,
			g_hInst,
			(LPVOID)this);

		if (NULL != m_hWnd) {
			createControls();
			initServer(false);
			layoutControls();
		}
	}

	return NULL != m_hWnd;
}

bool ExplorerBar::initServer(bool startIfNeeded) {
	if (m_server) {
		return true;
	}
	if (!startIfNeeded && !FindWindow(ServerWindowClass, NULL)) {
		return false;
	}

	if (!Util::VerifyActiveScriptDebugger() || !Util::VerifyDebugPreference()) {
		return false;
	}

	CComPtr<ICrossfireServerClass> serverClass = NULL;
	HRESULT hr = CoGetClassObject(CLSID_CrossfireServer, CLSCTX_ALL, 0, IID_ICrossfireServerClass, (LPVOID*)&serverClass);
	if (FAILED(hr)) {
		Logger::error("ExplorerBar.initServer(): CoGetClassObject() failed", hr);
		return false;
	}

//	HWND rootWindow = GetAncestor(m_hWndParent, GA_ROOT);
	hr = serverClass->GetServer(/*(unsigned long)rootWindow,*/ &m_server);
	if (FAILED(hr)) {
		Logger::error("ExplorerBar.initServer(): GetController() failed", hr);
		return false;
	}

	hr = m_server->getState(&m_serverState);
	if (FAILED(hr)) {
		Logger::error("ExplorerBar.initServer(): getState() failed", hr);
	}

	if (m_serverState != STATE_DISCONNECTED) {
		hr = m_server->getPort(&m_serverPort);
		if (FAILED(hr)) {
			Logger::error("ExplorerBar.initServer(): getPort() failed", hr);
		}
	}

	return true;
}

void ExplorerBar::layoutControls() {
	int x = SPACING_WIDTH;
	int y = SPACING_WIDTH;
	const int BUFFER_SIZE = 64;

	/* status label is always shown */
	switch (m_serverState) {
		case STATE_DISCONNECTED: {
			SetWindowText(m_statusLabel, L"Crossfire Debugger State: Disconnected");
			break;
		}
		case STATE_LISTENING: {
			std::wstring result;
			std::wstringstream stringStream;
			stringStream << L"Crossfire Debugger State: Listening on port ";
			stringStream << m_serverPort;
			result.assign(stringStream.str());
			SetWindowText(m_statusLabel, result.c_str());
			break;
		}
		case STATE_CONNECTED: {
			std::wstring result;
			std::wstringstream stringStream;
			stringStream << L"Crossfire Debugger State: Connected on port ";
			stringStream << m_serverPort;
			result.assign(stringStream.str());
			SetWindowText(m_statusLabel, result.c_str());
			break;
		}
	}

	HDC hDC = GetDC(m_statusLabel);
	LRESULT newFont = SendMessage(m_statusLabel, WM_GETFONT, 0, 0);
	HGDIOBJ oldFont = SelectObject(hDC, (HGDIOBJ)newFont);
	int length = GetWindowTextLength(m_statusLabel);
	RECT rect;
	TCHAR buffer[BUFFER_SIZE];
	GetWindowText(m_statusLabel, buffer, BUFFER_SIZE);
	DrawText(hDC, buffer, length, &rect, DT_CALCRECT);
	LONG width = rect.right - rect.left;
	LONG height = rect.bottom - rect.top;
	if (newFont) {
		SelectObject(hDC, oldFont);
	}
	ReleaseDC(m_statusLabel, hDC);
	SetWindowPos(m_statusLabel, 0, x, y + (m_portTextSize.y - height) / 2, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
	x += width + SPACING_WIDTH;

	/* vertical separator is always shown */
	EnableWindow(m_separator, m_server != NULL);
	SetWindowPos(m_separator, 0, x, y, SEPARATOR_WIDTH, m_portTextSize.y, SWP_NOZORDER | SWP_NOACTIVATE);
	x += SEPARATOR_WIDTH + SPACING_WIDTH;

	/* "port:" label */
	if (m_serverState != STATE_DISCONNECTED) {
		ShowWindow(m_portLabel, SW_HIDE);
	} else {
		ShowWindow(m_portLabel, SW_SHOW);
		hDC = GetDC(m_portLabel);
		newFont = SendMessage(m_portLabel, WM_GETFONT, 0, 0);
		oldFont = SelectObject(hDC, (HGDIOBJ)newFont);
		length = GetWindowTextLength(m_portLabel);
		GetWindowText(m_portLabel, buffer, BUFFER_SIZE);
		DrawText(hDC, buffer, length, &rect, DT_CALCRECT);
		width = rect.right - rect.left;
		height = rect.bottom - rect.top;
		if (newFont) {
			SelectObject(hDC, oldFont);
		}
		ReleaseDC(m_portLabel, hDC);
		SetWindowPos(m_portLabel, 0, x, y + (m_portTextSize.y - height) / 2, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
		x += width + SPACING_WIDTH;
	}

	/* port text */
	if (m_serverState != STATE_DISCONNECTED) {
		ShowWindow(m_portText, SW_HIDE);
		ShowWindow(m_portUpDown, SW_HIDE);
	} else {
		SendMessage(m_portUpDown, UDM_SETPOS32, 0, m_serverPort);
		ShowWindow(m_portText, SW_SHOW);
		ShowWindow(m_portUpDown, SW_SHOW);

		SetWindowPos(m_portText, 0, x, y, m_portTextSize.x, m_portTextSize.y, SWP_NOZORDER | SWP_NOACTIVATE);
		x += m_portTextSize.x;

		width = GetSystemMetrics(SM_CXVSCROLL);
		SetWindowPos(m_portUpDown, 0, x, y, width, m_portTextSize.y, SWP_NOZORDER | SWP_NOACTIVATE);
		x += width + SEPARATOR_WIDTH;
	}

	/* button is always shown */
	switch (m_serverState) {
		case STATE_DISCONNECTED: {
			SetWindowText(m_button, L"Listen");
			break;
		}
		case STATE_LISTENING: {
			SetWindowText(m_button, L"Stop");
			break;
		}
		case STATE_CONNECTED: {
			SetWindowText(m_button, L"Disconnect");
			break;
		}
	}
	hDC = GetDC(m_button);
	newFont = SendMessage(m_button, WM_GETFONT, 0, 0);
	if (newFont != 0) {
		oldFont = SelectObject(hDC, (HGDIOBJ)newFont);
	}
	GetWindowText(m_button, buffer, BUFFER_SIZE);
	DrawText(hDC, buffer, -1, &rect, DT_CALCRECT | DT_SINGLELINE);
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;
	if (newFont != 0) {
		SelectObject(hDC, oldFont);
	}
	ReleaseDC(m_button, hDC);
	width += 10;
	SetWindowPos(m_button, 0, x, y, width, m_portTextSize.y, SWP_NOZORDER | SWP_NOACTIVATE);
	x += width + SEPARATOR_WIDTH;

	/* clear the error text */
	SetWindowPos(m_errorLabel, 0, x, y + (m_portTextSize.y - height) / 2, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
	setErrorText(L"");
}

bool ExplorerBar::onCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) {
	if ((HWND)lParam != m_button) {
		return true;
	}

	if (HIWORD(wParam) != BN_CLICKED) {
		return true;
	}

	switch (m_serverState) {
		case STATE_LISTENING:
		case STATE_CONNECTED: {
			if (FAILED(m_server->stop())) {
				setErrorText(L"Failed to stop the Crossfire server");
			}
			break;
		}
		case STATE_DISCONNECTED: {
			TCHAR buffer[9];
			if (GetWindowText(m_portText, buffer, 9)) {
				int port = _wtoi(buffer);
				if (!(1000 <= port && port <= 65534)) {
					setErrorText(L"Valid port range: 1000-65534");
				} else {
					if (!initServer(true)) {
						setErrorText(L"Failed to initialize Crossfire server");
					} else {
						if (FAILED(m_server->start(port, 54124 /* debug port */))) {
							setErrorText(L"Failed to start the Crossfire server");
						}
					}
				}
			}
		}
	}

	return true;
}

bool ExplorerBar::onNCCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) {
	if (!m_hWnd) {
		m_hWnd = hWnd;
	}
	return true;
}

//bool ExplorerBar::onPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) {
//	if (hWnd != m_separator) {
//		return true;
//	}
//
//	RECT clientRect;
//	GetClientRect(m_separator, &clientRect);
//	int lineWidth = GetSystemMetrics (SM_CXBORDER);
//	clientRect.right = clientRect.left + lineWidth * 2;
//	HDC hDC = GetDC(m_separator);
//	DrawEdge(hDC, &clientRect, EDGE_ETCHED, BF_RIGHT);
//	ReleaseDC(m_separator, hDC);
//    return false;
//}

void ExplorerBar::onServerStateChanged(WPARAM wParam, LPARAM lParam) {
	m_serverState = wParam;
	if (m_serverState != STATE_DISCONNECTED) {
		m_serverPort = lParam;
	}
	initServer(false);
	layoutControls();

	if (m_serverState == STATE_CONNECTED) {
		HKEY key;
		LONG result = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\IBM\\IECrossfireServer", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL);
		if (result != ERROR_SUCCESS) {
			Logger::error("ExplorerBar.serverStateChanged(): RegCreateKeyEx() failed", result);
		} else {
			result = RegSetValueEx(key, L"LastPort", 0, REG_DWORD, (BYTE*)&m_serverPort, sizeof(unsigned int));
			if (result != ERROR_SUCCESS) {
				Logger::error("ExplorerBar.serverStateChanged(): RegSetValueEx() failed", result);
			}
			RegCloseKey(key);
		}
	}
}

LRESULT ExplorerBar::onWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	bool result = true;
	if (msg == ServerStateChangeMsg) {
		onServerStateChanged(wParam, lParam);
		return 0;
	}

	switch (msg) {
		case WM_COMMAND: {
			result = onCommand(hWnd, wParam, lParam);
			break;
		}
		case WM_NCCREATE: {
			result = onNCCreate(hWnd, wParam, lParam);
			break;
		}
		case WM_CTLCOLORSTATIC: {
			return (LRESULT)GetStockObject(NULL_BRUSH);
		}
//		case WM_PAINT: {
//			result = onPaint(hWnd, wParam, lParam);
//			break;
//		}
	}
	if (!result) {
		return 1;
	}
//	if (hWnd == m_separator) {
//		return CallWindowProc(staticProc, hWnd, msg, wParam, lParam);
//	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

void ExplorerBar::setErrorText(wchar_t* text) {
	SetWindowText(m_errorLabel, text);
	int length = (int)wcslen(text);
	if (length) {
		HDC hDC = GetDC(m_errorLabel);
		LRESULT newFont = SendMessage(m_errorLabel, WM_GETFONT, 0, 0);
		HGDIOBJ oldFont = SelectObject(hDC, (HGDIOBJ)newFont);
		RECT rect;
		DrawText(hDC, text, length, &rect, DT_CALCRECT);
		LONG width = rect.right - rect.left;
		LONG height = rect.bottom - rect.top;
		if (newFont) {
			SelectObject(hDC, oldFont);
		}
		ReleaseDC(m_errorLabel, hDC);
		SetWindowPos(m_errorLabel, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
		ShowWindow(m_errorLabel, SW_SHOW);
	} else {
		ShowWindow(m_errorLabel, SW_HIDE);
		SetWindowPos(m_errorLabel, 0, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
	}
}

LRESULT CALLBACK ExplorerBar::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	ExplorerBar *pThis = (ExplorerBar*)GetWindowLongPtr(hWnd, GWL_USERDATA);
	if (!pThis && msg == WM_NCCREATE) {
		LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
		pThis = (ExplorerBar*)(lpcs->lpCreateParams);
		SetWindowLongPtr(hWnd, GWL_USERDATA, (__int3264)(LONG_PTR)pThis);
	}

	if (pThis) {
		return pThis->onWndProc(hWnd, msg, wParam, lParam);
	}

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