#pragma once
#include "GUIFactory.h"

class Button : public GUIObject
{
private:
	bool _clicked;

public:
	Button(int x, int y, int w, int h, LPCSTR caption, GUIFactory* factory);
	virtual ~Button();

	bool IsClicked();

	virtual void CallBack(int param) override;

};

// callback to handle button click event from the common control
// we just call the GUIObject.CallBack() method
static LRESULT CALLBACK StaticBtnHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, const DWORD_PTR dwRefData) {

	GUIObject* Obj = reinterpret_cast<GUIObject*>(dwRefData);

	if (Obj->Contains(reinterpret_cast<HWND>(lParam))) {
		switch (uMsg) {

		case WM_COMMAND:
			if(HIWORD(wParam) == BN_CLICKED)
				Obj->CallBack(0);
		}
	}
	return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}


Button::Button(int x, int y, int w, int h, LPCSTR caption, GUIFactory* factory) : GUIObject(x, y, w, h, factory) {
	_hwnd = _factory->GUICreateButton(_x, _y, _w, _h, caption);
	_factory->ApplySubClassHandler(StaticBtnHandler, this);
}

Button::~Button() {
	_factory->RemoveSubClassHandler(StaticBtnHandler, this);
}

void Button::CallBack(int param) {
	_clicked = true;
}

bool Button::IsClicked() {
	if (_clicked) {
		_clicked = false;
		return true;
	}
	return false;
}


HWND WindowsGUIFactory::GUICreateWindow(RECT r, WNDPROC WindowFn) {

	HINSTANCE hInst = ::GetModuleHandle(NULL);

	LPCSTR WindowName = "TestWindow";

	if (RegisteredClasses.find(WindowName) != RegisteredClasses.end()) {
		WNDCLASSEXA wcex;
		memset(&wcex, 0, sizeof(WNDCLASSEX));

		wcex.cbSize = sizeof(WNDCLASSEX);
		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WindowFn;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInst;
		wcex.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
		wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground = NULL;
		wcex.lpszMenuName = NULL;
		wcex.lpszClassName = WindowName;
		wcex.hIconSm = NULL;

		if (!::RegisterClassExA(&wcex)) {
			PrintError(sc);
			MessageBox(NULL, L"Register class failed", L"Error", NULL);
			return NULL;
		}

		RegisteredClasses.insert(std::string(wcex.lpszClassName));
	}
	
	HWND hwnd = ::CreateWindowA(
		WindowName,
		"Title",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		r.right - r.left, r.top-r.bottom,
		NULL, NULL,
		hInst,
		NULL);

	if (!hwnd) {
		PrintError(sc);
		MessageBox(NULL, L"Create window failed", L"Error", NULL);
		return NULL;
	}

	::ShowWindow(hwnd, SW_SHOW);
	::UpdateWindow(hwnd);

	return hwnd;
}

HWND WindowsGUIFactory::GUICreateButton(int x, int y, int w, int h, LPCSTR caption) {
	HWND btn = ::CreateWindow(WC_BUTTON, NULL, WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, x, y, w, h, WindowHandle, NULL, NULL, NULL);
	::SetWindowTextA(btn, caption);
	return btn;
}

void WindowsGUIFactory::ApplySubClassHandler(SUBCLASSPROC proc, GUIObject* GuiObject) {
	::SetWindowSubclass(WindowHandle, proc, GuiObject->Id(), (DWORD_PTR)GuiObject);
}