/** 
 * @file
 * @brief System インターフェースの実装クラスクラス
 *
 * @author S.F.
 * @version $Id:
 * 2001/3/13 ぷよーんさんのライブラリを参考にWindowsメッセージ処理方法を変更
 * (参照・利用の許可はぷよーんさん(http://puyon.pns.to/)よりいただいてます。)
 * Copyright (C) 2000 Satoshi Fujiwara. All Rights Reserved.
 */

#if !defined(AFX_SystemImpl_H__64DBDEBB_81F1_4542_AAF7_B212CB9F4604__INCLUDED_)
/// 二重インクルード防止のための定義
#define AFX_SystemImpl_H__64DBDEBB_81F1_4542_AAF7_B212CB9F4604__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "sf.h" 

namespace sf {
	namespace system {
extern "C" {

	/** @ref System インターフェースの実装クラス. 
	 *
	 * システムインターフェースの実装クラスです。
	 * システムリソース利用する際は、System インターフェースを使用しますが、実際は仮想関数の仕組みにより、この実装クラスのメソッドが呼ばれます。
	 * これは、OSに依存する部分をこのクラスに隠蔽するために行っています */
	class SystemImpl : public System,sf::system::Win32
		{
			// Singletonをはしょるためのマクロ
			DECLARE_SINGLETON(SystemImpl)
			// LIFECYCLE //
			/// コンストラクタ
			SystemImpl();
		public:
			/// 処理するウィンドウメッセージを格納する
			typedef std::map<DWORD,WindowMessage * > WindowMessageMap;

			/// デストラクタ
			virtual ~SystemImpl();
			// OPERATORS //
			// OPERATIONS //
			/** WinMain から呼ばれるメソッド.
			 * WinMain()内からSystemImplをインスタンスを生成し、このメソッドを呼び出します。*/
			int winMain (const HINSTANCE hThisInstance, const HINSTANCE hPrevInstance,
				const LPSTR lpszCmdParam, const int nCmdShow);
			
			/** Windowsイベント 処理用. */
			static LRESULT CALLBACK wndFunc(HWND hwnd, UINT message, WPARAM wParam,  LPARAM lParam);
			
			/** 処理するウィンドウメッセージを追加する.
			 * 処理したいウィンドウメッセージをここで追加します。
			 * ここで追加されないメッセージは、デフォルトの処理が呼ばれます。
			 * @param value ウィンドウメッセージ
			 * @param pWindowMessage WindowMessageのポインタ */
			const bool addWindowMessage(const DWORD value,WindowMessage * pWindowMessage)
			{
				if(mWindowMessageMap[value] == NULL){
					mWindowMessageMap[value] = pWindowMessage;
					return true;
				} else {
					return false;
				}
			};

			virtual void wait(void);
			// エラー表示して終了
			virtual void errorTerminate(const wchar_t *errString);
			// エラー表示
			virtual void outputError(const wchar_t *errString);

			// ACCESS //
			virtual void  timerInterval(const unsigned long msValue){mTimerInterval = msValue;};	
			virtual const unsigned long timerInterval(void) const {return mTimerInterval;};
			virtual const DWORD time (void) const { return timeGetTime();};
			
			virtual console::Console * const console(void){ return mpConsole;};
			virtual sound::Sound * const sound(void){ return mpSound;};
			virtual input::Input * const input(void){ return mpInput;};
			
			virtual application::Main * const main(){return mpMain;}
			virtual void main(application::Main * const pMain ){mpMain = pMain;}

			// INQUIRY //
			virtual bool isActive(void) {return mIsWindowActive;};
			virtual const float deltaTime(void){return mFrameStep;};
			virtual const float framePerSec(void){return mFramePerSec;};
		private:
			/** 終了処理.
			 * 開放しなくいけないメモリ、Release()しなくてはいけないCOMインターフェースなどはここで開放します。*/
			void uninitialize(void);

			/** 現在ウィンドウがアクティブであるかどうか問い合わせる.
			 * @param true アクティブである
			 * @param false アクティブでない */
			const bool isWindowActive(void) const {return mIsWindowActive;};

			/** 現在ウィンドウがアクティブであるかどうか設定する.
			 * @param true アクティブである
			 * @param false アクティブでない */
			void windowActivate(const bool value){mIsWindowActive = value;};
			/** 内部タイマー変数を初期化する */
			void initTimer(void);
			/** mWindowMessageMap をセットアップする */
			void setupMessageMap(void);
			

			// Window Events
			/** WM_ABOUTメッセージの処理
			 * @param hwnd ウィンドウハンドル */
			LRESULT 	onAbout(const HWND hwnd);

			/** WM_COMMANDメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT 	onCommand(const HWND hwnd,const WPARAM wParam, const LPARAM lParam);

			/** WM_ACTIVATEメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT 	onActivate(const HWND hwnd,const WPARAM wParam,const LPARAM lParam);

			/** WM_MOVEメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT 	onMove(const HWND hwnd,const WPARAM wParam,const LPARAM lParam);

			/** WM_SIZEメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT 	onSize(const HWND hwnd,const WPARAM wParam,const LPARAM lParam);

			/** WM_PAINTメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT		onPaint(const HWND hwnd, const WPARAM wParam, const LPARAM lParam);

			/** WM_SYSCOMMANDメッセージの処理
			 * @param hwnd ウィンドウハンドル 
			 * @param wParam WPARAM 
			 * @param lParam LPARAM */
			LRESULT		onSysCommand(const HWND hwnd, const WPARAM wParam, const LPARAM lParam);
			
			HWND		mHWNDMain;///< メインウィンドウハンドル

			console::Console 	*mpConsole;///< console::Consoleインターフェースのポインタ
			sound::Sound 		*mpSound;///< sound::Soundインターフェースのポインタ
			input::Input		*mpInput;///< input::Inputインターフェースのポインタ

			::sf::application::Main 		*mpMain;///< ::sf::application::Mainインターフェースのポインタ
			
						
			bool 		mIsWindowActive;///< 現在ウィンドウがアクティブかどうか？
			bool		mbWindowed;///<ウィンドウモードかフルスクリーンモードか？
			
			DWORD		mTimerInterval;///< フレーム維持タイマーの間隔(ms)
			DWORD		mTimerValue;///< 現在のタイマーの値(ms)
			DWORD		mTimerBefore;///< 1フレーム前のタイマーの値(ms)
			DWORD		mTimerElapsed;///< 1フレーム中の諸々の処理に要した時間(ms)

			WindowMessageMap mWindowMessageMap;///< ウィンドウメッセージマップ
			float		mFrameStep;///< 1フレームの基本数値
			float		mFramePerSec;///< FPS値
			static		SystemImpl *pSystemImpl;///< 自分自身のポインタ
			// constant
			static const wchar_t smAppName[];///< アプリケーション名
		};// SystemImpl
		}
	}// namespace system
} // namespace sf
#endif // !defined(AFX_SystemImpl_H__64DBDEBB_81F1_4542_AAF7_B212CB9F4604__INCLUDED_)
