#include <windows.h>
#include <time.h>
#include <direct.h>

#include "dxddraw.h"
#include "dxdinput.h"
#include "dxdsound.h"
#include "mmsystem.h"

#define		FPS			10

#define		MENU_NAME	"My DirectX!!"
#define		CLASS_NAME	"My DirectX!!"


char			g_MainPath[256];
HWND			g_MainWnd=NULL;
HINSTANCE		g_MainIns=NULL;
BOOL 			g_bActiveOn=FALSE;

long			g_Width=800;
long			g_Height=600;
bool			g_bFullModeOn=false;

DWORD			g_TimeCur=0, g_TimeOld=0;
CDXDDraw		g_DDraw;
CDXDInput		g_DInput;
CDXDSound		g_DSound;

POINT			g_MousePt={0,0};
BYTE			g_Keyboard[256]={NULL,};
DIMOUSESTATE	g_MouseState;


#define		KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define		KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
#ifndef KEY_ON
#define KEY_ON(vlaue)		(g_DInput.KeyCheck(g_Keyboard, vlaue))
#define LBUT_ON				(g_MouseState.rgbButtons[0]&0x80)			
#define MBUT_ON				(g_MouseState.rgbButtons[1]&0x80)			
#define RBUT_ON				(g_MouseState.rgbButtons[2]&0x80)
#endif

/////////////////////////////////////////////////////////////////////////
// 여기서부터 시작..........
/////////////////////////////////////////////////////////////////////////

long g_Volume=100;
long g_Pan=0;

long g_Delay=0;

void KeyInput()
{	
	if(!g_bActiveOn)	return;		// 입력받지 않음.

	// 키보드 체크
	long mouseMoveValue = 1;

	g_DInput.GetKeyboardState(g_Keyboard);
	g_DInput.GetMouseState(&g_MouseState);
	
	g_MousePt.x+=(g_MouseState.lX*mouseMoveValue);
	g_MousePt.y+=(g_MouseState.lY*mouseMoveValue);

	if(g_MousePt.x<0)			g_MousePt.x=0;
	if(g_MousePt.y<0)			g_MousePt.y=0;
	if(g_MousePt.x>=g_Width)	g_MousePt.x=g_Width-1;
	if(g_MousePt.y>=g_Height)	g_MousePt.y=g_Height-1;
}

// 게임 프로시져...........
void GameProc(BOOL bActiveOn)
{
	KeyInput();

	if(KEY_ON(DIK_Q))	g_DSound.Play(0, true);
	if(KEY_ON(DIK_W))	g_DSound.Stop(0);

	if(KEY_ON(DIK_UP))
	{
		++g_Volume;
		if(g_Volume>100)	g_Volume=100;
		g_DSound.VolumeSet(g_Volume);
	}
	
	if(KEY_ON(DIK_DOWN))
	{
		--g_Volume;
		if(g_Volume<0)	g_Volume=0;
		g_DSound.VolumeSet(g_Volume);
	}
	
	if(KEY_ON(DIK_LEFT))
	{
		--g_Pan;
		if(g_Pan<-100)	g_Pan=-100;
	}

	if(KEY_ON(DIK_RIGHT))
	{
		++g_Pan;
		if(g_Pan>100)	g_Pan=100;
	}

	if(KEY_ON(DIK_SPACE))
	{
		if(g_Delay>0)	--g_Delay;
		if(g_Delay<=0)
		{
			g_DSound.Effect(1, 100, g_Pan);
			g_Delay=20;
		}

	}

	RECT rt;
	SetRect(&rt, 0, 0, 800, 600);
	g_DDraw.SurfaceToBack(0, 0, 0, rt);

	SetRect(&rt, 0, 0, 100, 100);
	g_DDraw.SurfaceToBackTrans(1, 0, 0, rt);

	char str[256];
	wsprintf(str, "볼륨=%03d, 소리방향=%03d", g_Volume, g_Pan);
	g_DDraw.PutString(600, 30, str);
	

	g_DDraw.PutString(g_MousePt.x,g_MousePt.y, "ㅁ");
	g_DDraw.Flip();						// 화면 갱신.
}

void ProgInit()
{
	g_DDraw.SurfaceCreate(0, "back.bmp");
	g_DDraw.SurfaceCreate(1, "spr.bmp", RGB(0,0,0));
	g_DSound.DSoundCreate(g_MainWnd);
	
	g_DSound.FileLoad(0, "back.wav");
	g_DSound.FileLoad(1, "gun.wav");
	g_DSound.Play(0, true);
}

void ProgRelease()
{
}

LRESULT CALLBACK WinMainProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	switch(iMsg)
	{
	case WM_CREATE:
		g_DInput.DInputCreate(hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
		//g_DInput.DInputCreate(hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_ACTIVATE:
		g_bActiveOn=(BOOL)wParam;
		g_DInput.AcquireCheck((BOOL) wParam);		// 다이렉트 인풋 얻기...
		return 0L;

	case WM_KEYDOWN:
		switch (wParam)
		{
			case VK_ESCAPE:
			case VK_F12:
				{
					PostMessage(hwnd, WM_CLOSE, 0, 0);
					return 0L;
				}
		}
		return 0;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

HWND WndCreate(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	WNDCLASS wc;
	wc.style	= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WinMainProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = 0;
	wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);

	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = MENU_NAME;
	wc.lpszClassName = CLASS_NAME;

	if(! RegisterClass(&wc))
	{
		MessageBox(NULL, "윈도우 생성 실패", CLASS_NAME, MB_OK);
		return FALSE;
	}
	
	HWND hwnd=NULL;
	if(g_bFullModeOn)
		hwnd=CreateWindow(CLASS_NAME, MENU_NAME, WS_POPUP,0, 0, g_Width, g_Height, NULL, NULL, hInstance, NULL);
	else
		hwnd=CreateWindow(CLASS_NAME, MENU_NAME, WS_OVERLAPPEDWINDOW, 0, 0, g_Width+16, g_Height+54, NULL, NULL, hInstance, NULL);

	// 윈도우를 가운데로 옮김...
	{
		RECT tempRt;
		GetClientRect(hwnd, &tempRt);
		int width = GetSystemMetrics(SM_CXSCREEN);
		int height = GetSystemMetrics(SM_CYSCREEN);
		int x = (width - tempRt.right) / 2;
		int y = (height - tempRt.bottom) / 2;
		int cx = tempRt.right;
		int cy = tempRt.bottom;
		MoveWindow(hwnd, x,y,cx,cy, TRUE);
	}
	
	
	g_DDraw.DDrawCreate(hwnd, g_Width, g_Height, 16, g_bFullModeOn);	// 다이렉트 드로우의 생성.

    //SetFocus(hwnd);
	ShowCursor(FALSE);	// 커서 안보이기.
	ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

	return hwnd;
}



// 메인...............
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	MSG msg;

	g_MainWnd=WndCreate(hInstance, hPrevInstance, szCmdLine, iCmdShow);
	if(!g_MainWnd)	return FALSE;
	_getdcwd(_getdrive(), g_MainPath, sizeof(g_MainPath));	// 경로명 알려주기......

	ProgInit();			// 프로그램 초기화...

	int tempRet=NULL;
	while(1)
	{
		tempRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
		if(tempRet != NULL)
		{
			if(msg.message == WM_QUIT) break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			GameProc(g_bActiveOn);
		}
	}
	ProgRelease();		// 프로그램 끝...

    return msg.wParam;
}
