/***************************************************************/
//
//
//		DirectX	[ window.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 5/11
/*---------------------------------------------------------------
■Update : 2017/5/11
			window.cppの作成

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/


//#include <Windows.h>
//#include <stdio.h>
//#include <d3dx9.h>

#include "window.h"
#include <time.h>

#include "system_component.h"

#include "game_manager.h"

//#pragma comment (lib,"d3d9.lib")
//#pragma comment (lib,"d3dx9.lib")
//#pragma comment (lib,"dxguid.lib")


/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/

#define CLASS_NAME APPLICATION_NAME							// ウィンドウクラスの名前

#define WIN_STYLE ( WS_OVERLAPPEDWINDOW \
	^ (WS_THICKFRAME & WS_SIZEBOX) )						// windowstyleのマクロ

#define TIMER_INTERVAL (1000/60)							// 発生間隔60分の1秒

/*----------------------------------------------------------------
	static member variable Initialize 
----------------------------------------------------------------*/

Window* Window::pWindow = nullptr;
const int Window::SCREEN_WIDTH = WINDOW_WIDTH; 
const int Window::SCREEN_HEIGHT = WINDOW_HEIGHT; 


// Window Constructor
Window::Window( )
	: hWnd( nullptr )
	, FPSCounter(0)
{

	// Registry WindowClassPointer
	if( !pWindow ){

		pWindow = this;
	}


}

// Window Destructor
Window::~Window( )
{

	// Do Nothing!!

}

// Window Create Instance 
Window* Window::Create( void )
{

	// Create Class Instance
	Window* pObject;
	pObject = new Window;

	return pObject;

}

// Window Initialize
bool Window::Init( HINSTANCE hInstance,	HINSTANCE hPravInstance, LPTSTR IpCmdLine, int nCmdShow )
{
	
	// THIS APPLICATION DONT USE STATUS 
	UNREFERENCED_PARAMETER( hPravInstance );
	
	// Registry WindowClass
	MyRegisterClass( hInstance );

	// Initialize Application
	if (!InitInstance ( hInstance, nCmdShow )){
		MessageBox( NULL, "Application Dont Play!!", "Application ERROR!!", 0 );
		return false;
	}
	
	{ // Initialize Process

		pManager = GameManager::Create( );
		pManager ->Init( hWnd, true );

	} // Application Initialize -> END

	return true;

}

// Window Uninitialize
int Window::Uninit( void )
{

	// Uninitialize Process
	pManager->Uninit( );

	// 以前にセットされた最小タイマ分解能をクリア
	timeEndPeriod( 1 );

	return (int) msg.wParam;

}

// Window Update
void Window::Application( void )
{

	// Update Process
	
	// 分解能の設定
	timeBeginPeriod( 1 );

	// 各カウンターの初期化
	DWORD dwFrameCount = 0;
	DWORD dwCurrentTime = 0;
	DWORD dwExecLastTime = timeGetTime();			// 現在の時刻をミリ秒単位で取得
	DWORD dwFPSLastTime = dwExecLastTime;			// 時間を同期
		
	//メッセ―ジループ
	for(;;){
		if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)!=0 ){
			//windowsの処理
			if(msg.message==WM_QUIT){
				break;
			}
			else{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else{
			dwCurrentTime = timeGetTime( );		// 現在の時刻をミリ秒単位で取得
			
			if( (dwCurrentTime-dwFPSLastTime) >= 500 ){

				FPSCounter=(dwFrameCount*1000)/(dwCurrentTime-dwFPSLastTime);
				dwFPSLastTime = dwCurrentTime;
				dwFrameCount=0;
			}
			if( (dwCurrentTime - dwExecLastTime) >= ( TIMER_INTERVAL ) ){

				dwExecLastTime=dwCurrentTime;	// 処理した時間を保存

				pManager->Update( );
				pManager->Draw( );
				dwFrameCount++;
			}
		}
	}

	

}

// Registry WindowClass
ATOM Window::MyRegisterClass(HINSTANCE hInstance)
{
	
	WNDCLASSEX wcex = {
		sizeof(WNDCLASSEX),							// WNDCALSSEXのメモリサイズを指定
		CS_CLASSDC,									// 表示するウィンドウのスタイルを設定
		WndProc,									//  ☆ ウィンドウプロシージャのアドレス(関数名)を指定
		0,											// 通常は使用しないので"0"を指定
		0,											// 通常は使用しないので"0"を指定x
		hInstance,									//  ☆ WinMainのパラメータのインスタンスハンドルを設定
		LoadIcon(hInstance, TEXT("KITTY")),			// 使用するアイコンを指定(Windowが持っているアイコンを使う)
		LoadCursor(NULL, IDC_CROSS),				// マウスカーソルを指定
		(HBRUSH)(COLOR_WINDOW + 1),					// ウィンドウのクライアント領域の背景色を設定
		NULL,										// Windowsにつけるメニューを設定
		CLASS_NAME,									//  ☆ ウィンドウクラスの名前
		NULL										// 小さいアイコンが設定された場合の情報を記述
	};

	return RegisterClassEx(&wcex);
;
	
}

// Create Window Process 
bool Window::InitInstance(HINSTANCE hInstance, int nCmdShow)
{


	RECT cr = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
	AdjustWindowRect( &cr, WIN_STYLE, FALSE );

	RECT dr = {};
	GetWindowRect( GetDesktopWindow( ),&dr );
	int windowX = (cr.right-cr.left)>(dr.right-dr.left) ? 0:((dr.right-dr.left)-(cr.right-cr.left))/2;
	int windowY = (cr.bottom-cr.top)>(dr.bottom-dr.top) ? 0:((dr.bottom-dr.top)-(cr.bottom-cr.top))/2;

	// ウィンドウを作成
	hWnd = CreateWindowEx(
	WS_EX_ACCEPTFILES,								// 拡張ウィンドウスタイル
	CLASS_NAME,										// ウィンドウクラスの名前
	APPLICATION_NAME,									// ウィンドウの名前
	WIN_STYLE,										// ウィンドウスタイル
	windowX,										// ウィンドウの左上X座標
	windowY,										// ウィンドウの左上Y座標
	cr.right-cr.left,								// ウィンドウの幅
	cr.bottom-cr.top,								// ウィンドウの高さ
	NULL,											// 親ウィンドウのハンドル
	NULL,											// メニューハンドルまたは子ウィンドウID
	hInstance,										// インスタンスハンドル
	NULL);											// ウィンドウ作成データ

   if (!hWnd)
   {
      return FALSE;
   }
	
	// ウィンドウの表示
	ShowWindow( hWnd, nCmdShow );
	UpdateWindow( hWnd );

	//renderer.Init( hWnd );

	return TRUE;
	
}

// Window Proc
LRESULT CALLBACK Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

	const char WINDOW_MSG[ ] = { "終了しますか？" };

	// Window Message
	switch( uMsg ){

		case WM_CLOSE:
			
			// Window終了処理
			if( MessageBox(NULL,WINDOW_MSG,APPLICATION_NAME, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDNO ){
				uMsg = NULL;
			}
			break;

		case WM_DESTROY:

			PostQuitMessage(0);
			break;

		case WM_KEYDOWN:

			// ESC終了処理
			if( wParam == VK_ESCAPE ) {					
				if( MessageBox(NULL,WINDOW_MSG,APPLICATION_NAME, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDYES ){
					DestroyWindow(hWnd);
				}
			}
			break;

		default:
			break;
	}

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

// Window Get Window Handle
HWND Window::GetWindowHandle( void )
{

	// Window Get Window Handle
	return pWindow->hWnd;

}

// Window Get Update Frame/Second
int Window::GetFPS( void )
{

	// Window Get Update Frame/Second
	return (pWindow->FPSCounter);

}




