// This is the main windows file to add to your project code so it works correctly.
// Please insert code ONLY between the points where you see these lines:

//Insert code here--------------------------
//Don't go past here------------------------

//Also: there are a couple sections that you might want to change, like the name
//of the window, these sections will be marked with a comment like this:

//Change this line!!!!!! <><><><><><><><><><><><><>


#include <windows.h>		//Windows header
#include <windowsx.h>		//Useful macros
#include <cstdio>
#include <cmath>
#include "Colors.h"
#include <string>
using namespace std;

//Defines /////////////////////////////////////////

//Window class
#define WINDOW_CLASS_NAME "WINCLASS"

//Globals /////////////////////////////////////////

int CAPP_WIDTH  = 640;		//This holds the width of the window
int CAPP_HEIGHT = 480;		//This holds the height of the window

//Function Templates //////////////////////////////

LRESULT CALLBACK WindowProc(HWND hwnd,
							UINT msg,
							WPARAM wparam,
							LPARAM lparam);

//Insert code here -------------------------- (Only function declarations that are in THIS file.)

void Line(int, int, int, int, COLORREF, HWND, int linetype = PS_SOLID);	//Don't remove this
void Rect(int, int, int, int, COLORREF, HWND);	//Don't remove
void Circle(int, int, int, COLORREF, HWND);			//Don't remove
void OutText(COLORREF, string, HWND,int x = NULL, int y = NULL);	//Don't remove

//Don't go past here ------------------------


//This is the WINMAIN function, it acts like the main() function in a normal console program

int WINAPI WinMain(HINSTANCE hinstance,
				   HINSTANCE hprevinstance,
				   LPSTR lpcmdline,
				   int ncmdshow)
{

	WNDCLASSEX	winclass;		//This is our window that we are creating
	HWND		hwnd;			//This is the window's handle (a name of sorts)
	MSG			msg;			//This will hold the window's messages

	//We have to fill in the window's class structure:
	winclass.cbSize		= sizeof(WNDCLASSEX);
	winclass.style		= CS_DBLCLKS | CS_OWNDC |		//For more information please refer to
						  CS_HREDRAW | CS_VREDRAW;		//the win32 SDK
	winclass.lpfnWndProc	= WindowProc;
	winclass.cbClsExtra		= 0;
	winclass.cbWndExtra		= 0;
	winclass.hInstance		= hinstance;
	winclass.hIcon			= LoadIcon(NULL, IDI_WINLOGO);
	winclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName	= NULL;
	winclass.lpszClassName	= WINDOW_CLASS_NAME;
	winclass.hIconSm		= LoadIcon(NULL, IDI_WINLOGO);

	//We have to register this class with windows (let it know we made a window)
	if (!RegisterClassEx(&winclass))
		return(0);	//If we can't register the class, end the program
	
	//Now we have to create the window
	if (!(hwnd = CreateWindowEx(NULL,
								WINDOW_CLASS_NAME,
								"Polymorphism Example",		//Change this line!!!!<><><><><><><>
								WS_OVERLAPPEDWINDOW | WS_VISIBLE,
								0,0,
								CAPP_WIDTH,CAPP_HEIGHT,
								NULL,
								NULL,
								hinstance,
								NULL)))
		return(0);	//If we can't create the window, end the program

	//Get the device context
	HDC hdc = GetDC(hwnd);

	//Insert code here------------------------------------------
	Line(50, 50, 200, 200, Color_Red, hwnd, PS_DOT);			//Can be deleted
		//Posible values for linestyle:
		//		PS_SOLID		Solid line
		//		PS_DASH			Dashed line
		//		PS_DOT			Dotted line
		//		PS_DASHDOT		Alternating dashes and dots
		//		PS_DASHDOTDOT	Alternating dashes and double dots
		//		This can also be omitted
	Circle(320, 240, 300, Color_Green, hwnd);					//Can be deleted
	Rect(100, 100, 200, 200, Color_Blue, hwnd);					//Can be deleted
	string s1 = "This is printed";								//   [|]
	string s2 = "This too";										//	 [|]
	string s3 = "Of course, I could print here!";				//   [|]
	OutText(Color_Green, s1, hwnd);								//   [|]
	OutText(Color_Red, s2, hwnd);								//	 [|]
	OutText(Color_Blue, s3, hwnd, 320, 240);					//	 [|]
	OutText(Color_Red, s1, hwnd);						 		//   [|]
	OutText(Color_Pink, "Then it goes here", hwnd);				//   \|/ 
	//Don't go past here----------------------------------------

	//This is the main event loop

	while(GetMessage(&msg,NULL,0,0))
	{
		//Translate accelerator keys
		TranslateMessage(&msg);

		//send the message to the window proc
		DispatchMessage(&msg);

	}//end while

	//Release the device context
	ReleaseDC(hwnd, hdc);

	//This is how we end in a windows program
	return(msg.wParam);

}//End of WinMain

//==================================================================================

LRESULT CALLBACK WindowProc(HWND hwnd,
							UINT msg,
							WPARAM wparam,
							LPARAM lparam)
{
	PAINTSTRUCT ps;			//This is for repainting the window
	HDC			hdc;		//Handle to a device context

	switch(msg)
	{
	case WM_CREATE:
		{
			//Insert Code Here ---------------------------
			//This part of the program is what is called when it is started.
			//Create your objects here, but make them static if you are going to use
			//them many times.


			//Don't go past here -------------------------
			return(0);
		}break;

	case WM_PAINT:
		{
			//Invalidate the entire window
			InvalidateRect(hwnd,NULL,FALSE);
			//Validate the window
			hdc = BeginPaint(hwnd,&ps);

			EndPaint(hwnd,&ps);	//End the painting process

			return(0);
		}break;

	case WM_DESTROY:
		{
			//This is what is called when the window is closed.
			PostQuitMessage(0);

			return(0);
		}break;

	case WM_SIZE:
		{
			int CAPP_WIDTH	= (int)LOWORD(lparam);
			int CAPP_HEIGHT = (int)HIWORD(lparam);
		}break;

	default:break;
	}//End Switch

	//This is where we process any messages that we haven't taken care of,
	//and the following will call the default windows message handler.

	return(DefWindowProc(hwnd, msg, wparam, lparam));

}//End of WindowProc

//==================================================================================

void Line(int x1, int y1, int x2, int y2, COLORREF color,
		  HWND hwnd, int linetype)
{

	HDC hdc = GetDC(hwnd);		//Get the device context of the window
	
	HPEN draw_pen = CreatePen(linetype, 1, color);	//Make a pen
	HPEN old_pen  = (HPEN)SelectObject(hdc, draw_pen);	//Make another pen

	MoveToEx(hdc,x1,y1,NULL);		//Move to the starting position
	LineTo(hdc, x2,y2);				//Make a line to the ending position
	
	SelectObject(hdc, old_pen);		//Select the old pen
	DeleteObject(draw_pen);			//Delete the drawing pen
	DeleteObject(old_pen);			//Delete the old pen

	ReleaseDC(hwnd,hdc);			//Release the device context

}

//==================================================================================

void Rect(int x1, int y1, int x2, int y2, COLORREF color, HWND hwnd)
{
	HDC hdc = GetDC(hwnd);			//Get the device context of the window

	HPEN draw_pen	  = CreatePen(PS_SOLID, 1, color);		//Make a solid pen
	HBRUSH draw_brush = CreateSolidBrush(color);			//Make a solid brush

	SelectObject(hdc,draw_pen);					//Select the pen
	SelectObject(hdc, draw_brush);				//Select the brush

	RECT rect = { x1,y1,x2,y2 };				//Make a rect object

	FillRect(hdc, &rect, draw_brush);			//Draw the rectangle

	DeleteObject(draw_pen);						//Delete the drawing pen
	DeleteObject(draw_brush);					//Delete the drawing brush

	ReleaseDC(hwnd,hdc);						//Release the device context

}

//==================================================================================

void Circle(int x, int y, int rad, COLORREF color, HWND hwnd)
{
	
	HDC hdc = GetDC(hwnd);		//Get the device context of the window

	HPEN draw_pen	  = CreatePen(PS_SOLID, 1, color);		//Make a solid pen
	HBRUSH draw_brush = CreateSolidBrush(color);			//Make a solid brush

	SelectObject(hdc, draw_brush);							//Select the brush

	x = x - (rad /2);										//Find the center of the circle
	y = y - (rad /2);										//same

	int x2 = x + rad;										//Create the second set of vars
	int y2 = y + rad;

	Ellipse(hdc, x, y, x2, y2);								//Create a circular ellipse

	DeleteObject(draw_brush);								//Delete the brush
	DeleteObject(draw_pen);									//Delete the pen

	ReleaseDC(hwnd,hdc);			//Release the device context

}

//==================================================================================

void OutText(COLORREF color, string str, HWND hwnd,
			int x, int y)
{
	static int xpos = 0;		//Make static variables to hold the position of the text so it
	static int ypos = 0;		//doesn't overwrite itself each time you print


	if (x != NULL)				//Check to see if the user is specifying a position for the text
		xpos = x;				//and if so, set it.
	if (y != NULL)
		ypos = y;


	HDC hdc = GetDC(hwnd);			//Get the device context of the window

	SetTextColor(hdc,color);		//Set the color of the text

	SetBkColor(hdc,RGB(0,0,0));		//Set the backround color to black
	
	SetBkMode(hdc,TRANSPARENT);			//Set text mode to OPAQUE

	TextOut(hdc,xpos,ypos,str.c_str(),str.size());	//Write the text to the screen


	ypos+=16;		//Move to the next line
	xpos = 0;		//Move to the beginning of the line

	ReleaseDC(hwnd,hdc);		//Release the device context
}