/* Copyright (c) 2008, Antonie Jovanoski
 *	
 * 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, 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, see <http://www.gnu.org/licenses/>.
 */

#include "wndclass.h"

//-----------------------------------------------------------------------
// Constructor
// hInstance - instanche
// width, height - dimension if the window
//-----------------------------------------------------------------------

Window::Window(HINSTANCE hInstance, int width, int height)
:	m_hWnd(NULL), m_hInst(NULL)
{
	m_hInst = hInstance;

	WNDCLASSEX wcex;
	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= Window::s_WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= m_hInst;
	wcex.hIcon			= NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= L"D3D10";
	wcex.hIconSm		= NULL;

	RegisterClassEx(&wcex);
	
	RECT rc = {0, 0, width, height};
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
	m_hWnd = CreateWindow(L"D3D10", L"DirectX 10", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 
		rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, m_hInst, NULL);

	if(!m_hWnd)
		return;

	SetWindowLongPtr(m_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
}

//--------------------------------------------------------------------------
// Return window handle
//--------------------------------------------------------------------------

HWND Window::GetHwnd() const
{
	return m_hWnd;
}

//--------------------------------------------------------------------------
// Return instance handle
//--------------------------------------------------------------------------

HINSTANCE Window::GetInstance() const
{
	return m_hInst;
}

//--------------------------------------------------------------------------
//Window message callback function
//--------------------------------------------------------------------------

LRESULT CALLBACK Window::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	Window *window = 0;

	window = reinterpret_cast<Window *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
	if(window){
		return window->HandleMessage(uMsg, wParam, lParam);
	}		
	
	return DefWindowProc(hwnd, uMsg, wParam, lParam);	
}

//------------------------------------------------------------------------
// Process window message here
//------------------------------------------------------------------------

LRESULT Window::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	HDC hDC;

	switch(uMsg){
		case WM_DESTROY:
			//SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
			PostQuitMessage(0);
			return 0;

		case WM_PAINT:
			PAINTSTRUCT ps;
			hDC = BeginPaint(m_hWnd, &ps);
			EndPaint(m_hWnd, &ps);
			return 0;

		case WM_SIZE:
			OnResize(LOWORD(lParam), HIWORD(lParam));
			return 0;

		case WM_KEYDOWN:
			OnKeyDown((UINT)wParam, (UINT)lParam);
			return 0;

		case WM_LBUTTONDOWN:
			OnMouseLeftDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (UINT)wParam);
			return 0;

		case WM_MOUSEMOVE:
			OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (UINT)wParam);
			return 0;

		case WM_LBUTTONUP:
			OnMouseLeftUp(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (UINT)wParam);
			return 0;
	}

	return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}

//--------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------

Window::~Window()
{
}

//--------------------------------------------------------------------------
// Override to get window resize notification
//--------------------------------------------------------------------------

void Window::OnResize(int width, int height)
{
}

//--------------------------------------------------------------------------
// Override to get key down (virtual) notification
//--------------------------------------------------------------------------

void Window::OnKeyDown(UINT vkey, UINT flags)
{
}

//--------------------------------------------------------------------------
// Override to get mouse left key press notification
// x, y position of the cursor
// flags - wParam, see MSDN documentation for WM_LBUTTONDOWN
//--------------------------------------------------------------------------

void Window::OnMouseLeftDown(int x, int y, UINT flags)
{
}

//--------------------------------------------------------------------------
// Override to get mouse move notification
// x, y position of the cursor
// flags - wParam, see MSDN documentation for WM_MOUSEMOVE
//--------------------------------------------------------------------------

void Window::OnMouseMove(int x, int y, UINT flags)
{
}

//--------------------------------------------------------------------------
// Override to get mouse left key released
// x, y position of the cursor
// flags - wParam, see MSDN documentation for WM_LBUTTONUP
//--------------------------------------------------------------------------

void Window::OnMouseLeftUp(int x, int y, UINT flags)
{
}

//--------------------------------------------------------------------------
// returns window client width
//--------------------------------------------------------------------------

unsigned int Window::GetWidth() const
{
	RECT rc;
	GetClientRect(m_hWnd, &rc);
	return rc.right - rc.left;
}

//-------------------------------------------------------------------------
// returns window client height
//-------------------------------------------------------------------------

unsigned int Window::GetHeight() const
{
	RECT rc;
	GetClientRect(m_hWnd, &rc);
	return rc.bottom - rc.top;
}
