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

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


#include "window.h"
#include "resource.h"

#include <time.h>

#include "system_component.h"

#include "game_manager.h"

#include "imgui.h"
#include "imgui_impl_dx9.h"

/*---------------------------------------------------------------
	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 
----------------------------------------------------------------*/

const int Window::SCREEN_WIDTH  = WINDOW_WIDTH; 
const int Window::SCREEN_HEIGHT = WINDOW_HEIGHT; 
Window* Window::pWindow = nullptr;
std::map<unsigned int,MethodFunc> Window::CallBackMethod;

int Window::height = 0;
int Window::width  = 0;




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

	// Registry WindowClassPointer
	if( !pWindow ){
		pWindow = this;
	}

	// Add Msg < Method >
	CallBackMethod[WM_CLOSE]     = ProcMethod::CloseWinMsg;
	CallBackMethod[WM_DESTROY]   = ProcMethod::DestoryWinMsg;
	CallBackMethod[WM_KEYDOWN]   = ProcMethod::KeydownWinMsg;

	// for drop file
	CallBackMethod[WM_CREATE]    = ProcMethod::CreateWinMsg;
	CallBackMethod[WM_DROPFILES] = ProcMethod::DropFileWinMsg;

	// for tool method

}

// 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 );

	return TRUE;
	
}

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

    if (ImGui_ImplDX9_WndProcHandler(hWnd, uMsg, wParam, lParam))
        return true;

	// Window Message
	if( CallBackMethod.find(uMsg) != CallBackMethod.end() ){
		CallBackMethod[uMsg](hWnd,uMsg,wParam,lParam);
	}
	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);

}







