/***************************************************************************/
/** @file       window.cpp
    @brief      アプリケーション(ウィンドウ)の実装
    @author     shom
    @internal
****************************************************************************/

#include "pch_core.h"

#include "window.h"

#include "window_def.h"

#include "core/app.h"


using namespace window_def;


namespace
{
	b32 s_bWindowClose = FALSE;

	b32 s_bWindowActive = TRUE;
	b32 s_bMessageBoxAppearing = FALSE;

	u32 s_uClientWidth  = sc_client_width_init;
	u32 s_uClientHeight = sc_client_height_init;
	u32 s_uWindowPosX   = sc_window_pos_x_init;
	u32 s_uWindowPosY   = sc_window_pos_y_init;
}


/***************************************************************************
	window( namespace )
****************************************************************************/

#ifdef DX

HWND	window::InitApp( HINSTANCE hinst, int nCmdShow )
{
	///ウィンドウクラスの登録
	WNDCLASSEX	wc	=
	{
		sizeof( WNDCLASSEX ),			// この構造体のサイズ
		NULL,							// ウインドウのスタイル(default)
		(WNDPROC)callback_msg_proc,		// メッセージ処理関数の登録
		0, 0,							// 通常は使わないので常に0
		hinst,							// インスタンスへのハンドル
		NULL,							// アイコン
		LoadCursor( NULL, IDC_ARROW ),	// カーソルの形
		WHITE_BRUSH, NULL,				// 背景なし、メニュー
		sc_sz_wnd_class_name,			// クラス名の指定
		NULL							// 小アイコン
	};

	if( RegisterClassEx( &wc ) == 0 )
	{
		DEBUG_BREAK();
		return NULL;
	}

	///メイン・ウィンドウの作成
	HWND h_wnd;
	{
		h_wnd = CreateWindow(
					sc_sz_wnd_class_name, sc_sz_wnd_name, 
					~(WS_MAXIMIZEBOX | WS_THICKFRAME) & WS_OVERLAPPEDWINDOW, 
					//最大化ボタンを持たない・境界変更のできない
					0, 0, s_uClientWidth, s_uClientHeight, 
					GetDesktopWindow(),
					NULL, hinst, NULL
					);
	}{ ASSERT( h_wnd ); }

	//ウィンドウサイズの再設定
	//--ウィンドウサイズをクライアント領域の大きさとして指定したため）
	RECT cRect, wRect;
	if( GetClientRect( h_wnd, &cRect ) == 0 )
	{
		DEBUG_BREAK();
		return NULL;
	}
	if( GetWindowRect( h_wnd, &wRect ) == 0 )
	{
		DEBUG_BREAK();
		return NULL;
	}
	int ww = s_uClientWidth +
			 ((wRect.right - wRect.left) - (cRect.right - cRect.left));
	int wh = s_uClientHeight +
			 ((wRect.bottom - wRect.top) - (cRect.bottom - cRect.top));

	if( SetWindowPos( h_wnd, HWND_TOP, s_uWindowPosX, s_uWindowPosY,
					  ww, wh, SWP_SHOWWINDOW ) == 0 )
	{
		DEBUG_BREAK();
		return NULL;
	}

	///ウィンドウの表示
	ShowWindow( h_wnd, nCmdShow );
	UpdateWindow( h_wnd );

	///WM_PAINTを利用しない
	ValidateRect( h_wnd, 0 );

	return h_wnd;
}

int		window::FinApp( HWND h_wnd, HINSTANCE h_inst )
{
	if( !s_bWindowClose )
	{
		VERIFY( DestroyWindow( h_wnd ) != 0 );
	}

	///ウィンドウクラスの登録解除
	if( UnregisterClass( sc_sz_wnd_class_name, h_inst ) == 0 )
	{
		DXTRACE_ERR( _T( "WinMain UnregisterClass" ), GetLastError() );
		return -1;
	}

	return 0;
}


/**
 * メッセージ処理用コールバック関数
 * 
 * @param h_wnd		ウィンドウハンドル
 * @param msg		メッセージ
 * @param w_param	メッセージの最初のパラメータ
 * @param l_param	メッセージの2番目のパラメータ
 * 
 * @return 成功: メッセージ処理結果か0  失敗: -1
 */

// *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
namespace
{
	b32		destroy_window( HWND h_wnd )
	{
		if( DestroyWindow( h_wnd ) == 0 )
		{
			DEBUG_BREAK();

			return FALSE;
		}
		else
		{
			s_bWindowClose = TRUE;

			return TRUE;
		}		
	}
}
// *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *

LRESULT CALLBACK	window::callback_msg_proc(
	HWND   h_wnd,
	UINT   msg,
	WPARAM w_param,
	LPARAM l_param
	)
{
	switch( msg )
	{
		case WM_DESTROY:  // - ウィンドウ破棄 -
			{
				///メッセージ処理を終了
				PostQuitMessage(0);	//WM_QUIT送信
	
				///ゲームループ終了
				app::StopAppLoop();
	
				return S_OK;
			}
			//break;

		case WM_CLOSE:	  // - ×が押された -
			{
				const b32 b_destory_window = destroy_window( h_wnd );

				// ウィンドウを破棄、case:WM_DESTROYへ制御を移す
				return b_destory_window ? S_OK : E_FAIL;
			}
			//break;

		case WM_KEYDOWN:  // - キーが押された -
			{
				//ESCキー：アプリケーションを終了
				if( (int)w_param == VK_ESCAPE )
				{
					//確認ダイアログを出す
					s_bMessageBoxAppearing = TRUE;
					int	result	= MessageBoxEx(
							h_wnd, _T( "中断しますか？" ), sc_sz_wnd_name,
							MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2,
							LANG_JAPANESE
							);
					s_bMessageBoxAppearing = FALSE;
	
					ASSERT( result != 0 );
					if( result != IDNO/*choise cancel*/ )
					{
						//ウィンドウを破棄、case:WM_DESTROYへ制御を移す
						destroy_window( h_wnd );
					}
				}
	
				return 0;
			}
			//break;

		case WM_ACTIVATE:	//ウィンドウのアクティブ化・非アクティブ化
			{
				if( w_param == WA_INACTIVE )
					//非アクティブ化
				{
					s_bWindowActive  = FALSE;
				}
				else
					//アクティブ化
				{
					///インプットの復帰
					//restart_device();

					s_bWindowActive  = TRUE;
				}
	
				return 0;
			}
			//break;

		default:	//デフォルトのメッセージ処理
			{
				return DefWindowProc( h_wnd, msg, w_param, l_param );
			}
			//break;
	}
}

#endif	//DX

b32		window::IsWindowActive()
{
	return s_bWindowActive;
}

b32		window::IsMessageBoxAppearing()
{
	return s_bMessageBoxAppearing;
}

u32		window::GetClientWidth()
{
	return s_uClientWidth;
}

u32		window::GetClientHeight()
{
	return s_uClientHeight;
}

void	window::SetClientWidth( u32 width )
{
	s_uClientWidth = width;
}

void	window::SetClientHeight( u32 height )
{
	s_uClientHeight = height;
}

u32		window::GetWindowPosX()
{
	return s_uWindowPosX;
}

u32		window::GetWindowPosY()
{
	return s_uWindowPosY;
}

void	window::SetWindowPosX( u32 x )
{
	s_uWindowPosX = x;
}

void	window::SetWindowPosY( u32 y )
{
	s_uWindowPosY = y;
}


