#include <windows.h>

#include "resource.h"

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass="omokpan";


int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
					 ,LPSTR lpszCmdParam,int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;

	g_hInst=hInstance;
	
	WndClass.cbClsExtra=0;
	WndClass.cbWndExtra=0;
	WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	WndClass.hInstance=hInstance;
	WndClass.lpfnWndProc=(WNDPROC)WndProc;
	WndClass.lpszClassName=lpszClass;
	WndClass.lpszMenuName=NULL;
	WndClass.style=CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);
	
	hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,(HMENU)NULL,hInstance,NULL);
	ShowWindow(hWnd,nCmdShow);
	
	while(GetMessage(&Message,0,0,0)) 
	{
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}

	return Message.wParam;
}

#define  MAX_X   19
#define  MAX_Y   19

int g_data[MAX_Y][MAX_X]={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
						{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};


int mx; int my; int xpos; int ypos;

int player = 1;
int nStartPosX=30;
int	nStartPosY=30;
int nWBlock=30;
int nHBlock=30;
int nWPan=(MAX_X-1)*nWBlock;
int nHPan=(MAX_Y-1)*nHBlock;
HBITMAP  hBit_Wood;
HBITMAP  hBit_BStone;
HBITMAP  hBit_WStone;

// 투명 비트맵을 출력하는 함수. (x,y)에 출력 위치. clrMask에 투명색을 준다.
void TransBlt(HDC hdc, int x, int y, HBITMAP hbitmap, COLORREF clrMask)
{
	BITMAP bm;
	COLORREF cColor;
	HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
	HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
	HDC		hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
	POINT	ptSize;
	
	hdcTemp = CreateCompatibleDC(hdc);
	SelectObject(hdcTemp, hbitmap);
	GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&bm);
	ptSize.x = bm.bmWidth;
	ptSize.y = bm.bmHeight;
	DPtoLP(hdcTemp, &ptSize,1);
	
	hdcBack   = CreateCompatibleDC(hdc);
	hdcObject = CreateCompatibleDC(hdc);
	hdcMem    = CreateCompatibleDC(hdc);
	hdcSave   = CreateCompatibleDC(hdc);
	
	bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
	bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
	bmAndMem    = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
	bmSave      = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
	
	bmBackOld   = (HBITMAP) SelectObject(hdcBack, bmAndBack);
	bmObjectOld = (HBITMAP) SelectObject(hdcObject, bmAndObject);
	bmMemOld    = (HBITMAP) SelectObject(hdcMem, bmAndMem);
	bmSaveOld   = (HBITMAP) SelectObject(hdcSave, bmSave);
	
	SetMapMode(hdcTemp, GetMapMode(hdc));
	
	BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
	
	cColor = SetBkColor(hdcTemp, clrMask);
	
	BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
	
	SetBkColor(hdcTemp, cColor);
	
	BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
	BitBlt(hdcMem , 0, 0, ptSize.x, ptSize.y, hdc      , x, y, SRCCOPY);
	BitBlt(hdcMem , 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
	BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack  , 0, 0, SRCAND);
	BitBlt(hdcMem , 0, 0, ptSize.x, ptSize.y, hdcTemp  , 0, 0, SRCPAINT);
	BitBlt(hdc    , x, y, ptSize.x, ptSize.y, hdcMem   , 0, 0, SRCCOPY);
	BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave  , 0, 0, SRCCOPY);
	
	DeleteObject(SelectObject(hdcBack, bmBackOld));
	DeleteObject(SelectObject(hdcObject, bmObjectOld));
	DeleteObject(SelectObject(hdcMem, bmMemOld));
	DeleteObject(SelectObject(hdcSave, bmSaveOld));
	
	DeleteDC(hdcMem);
	DeleteDC(hdcBack);
	DeleteDC(hdcObject);
	DeleteDC(hdcSave);
	DeleteDC(hdcTemp);
}

void RunInit(HWND hWnd, WPARAM wParam, LPARAM lParam) 
{

} 

//1 = 흑돌 
//2 = 백돌 
void RunPaint(HWND hWnd, WPARAM wParam, LPARAM lParam, HINSTANCE hInst) 
{
	HDC          hdc, MemDC;  
	PAINTSTRUCT  ps;  
	HBITMAP      OldBitmap;
	HPEN         hPen, OldPen;

    hdc = BeginPaint(hWnd, &ps);  
	MemDC=CreateCompatibleDC(hdc);
	hPen=CreatePen(PS_SOLID, 2, RGB(0,0,0));
    OldPen=(HPEN)SelectObject(hdc, hPen);
	OldBitmap=(HBITMAP)SelectObject(MemDC, hBit_Wood);     
	BitBlt(hdc,0,0, nWPan+(nStartPosX<<1),nHPan+(nStartPosY<<1),MemDC,0,0,SRCCOPY); 
    SelectObject(MemDC, OldBitmap);
	DeleteDC(MemDC);    

	for(ypos=0; ypos <= nHPan; ypos+=nHBlock)
	{		
		MoveToEx(hdc, nStartPosX, nStartPosY+ypos, NULL);
		LineTo(hdc, nStartPosX+nWPan, nStartPosY+ypos);
	}

	for(xpos=0; xpos <= nWPan; xpos+=nWBlock)   
	{ 		
		MoveToEx(hdc, nStartPosX+xpos, nStartPosY, NULL);
	    LineTo(hdc, nStartPosX+xpos, nStartPosY+nHPan);
	}

    for(my=0; my < MAX_Y; my++)
	{
		for(mx=0; mx < MAX_X; mx++)   
		{ 
            if(1 == g_data[my][mx])    
			{ 		
				xpos = (mx*nHBlock)-((nHBlock-10)>>1);    
				ypos = (my*nWBlock)-((nWBlock-10)>>1);    
				TransBlt(hdc, nStartPosX+xpos, nStartPosY+ypos, hBit_BStone, RGB(255,0,255));
			}else if(2 == g_data[my][mx])    
			{
				xpos = (mx*nHBlock)-((nHBlock-10)>>1);    
				ypos = (my*nWBlock)-((nWBlock-10)>>1);    
				TransBlt(hdc, nStartPosX+xpos, nStartPosY+ypos, hBit_WStone, RGB(255,0,255));
			}   
		}
	}
	SelectObject(hdc, OldPen);
	DeleteObject(hPen);
	EndPaint(hWnd, &ps); 
} 

void RunLButton(HWND hWnd, WPARAM wParam, LPARAM lParam, HINSTANCE hInst) 
{
	RECT  rt;
	
	mx = LOWORD(lParam);  	
	my = HIWORD(lParam);

    xpos = (mx-(nStartPosX-(nWBlock>>1)))/nWBlock;  
	ypos = (my-(nStartPosY-(nHBlock>>1)))/nHBlock;

	if (xpos < 0 || xpos >= MAX_X ||
		ypos < 0 || ypos >= MAX_Y) 
	{
		return ;
	}

	if(0 == g_data[ypos][xpos])  
	{
		g_data[ypos][xpos] = player;  
		player=(player==1) ? 2 : 1;
		
		SetRect(&rt, nStartPosX-(nWBlock>>1)+(xpos*nWBlock),
			         nStartPosY-(nHBlock>>1)+(ypos*nHBlock),
			         nStartPosX-(nWBlock>>1)+((xpos+1)*nWBlock),
			         nStartPosY-(nHBlock>>1)+((ypos+1)*nHBlock));
		
		InvalidateRect(hWnd, &rt, FALSE); 
	}else{
		MessageBox(hWnd,"돌이 이미 존재 합니다.","알림",MB_OK|MB_ICONEXCLAMATION);
	}
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch(iMessage) 
	{
	case WM_CREATE:
		hBit_Wood  =LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP_WOOD)); 
		hBit_BStone=LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP_BSTONE)); 
		hBit_WStone=LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP_WSTONE)); 
		return 0;

	case WM_LBUTTONDOWN:
        RunLButton(hWnd, wParam, lParam, g_hInst);
		return 0;

	case WM_PAINT:
        RunPaint(hWnd, wParam, lParam, g_hInst);
		return TRUE;

	case WM_DESTROY:
		if (hBit_Wood)   DeleteObject(hBit_Wood);
		if (hBit_BStone) DeleteObject(hBit_BStone);
		if (hBit_WStone) DeleteObject(hBit_WStone);
		PostQuitMessage(0);
		return 0;
	}

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