#pragma once

#include "refCActivity.h"
#include "refCWindow.h"
#include "共通\refCAtom.h"

using namespace System::Collections::Generic;

namespace FDK
{
	public ref class CApplicationBase
	{
	public:

		property CWindow^ Window
		{
			CWindow^ get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
				return this->_Window;
			}
			void set( CWindow^ value )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );

				this->_Window = value;
				this->_hWindow = value->Handle;	// こちらも変更する。
			}
		}
		property IntPtr hWindow
		{
			IntPtr get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
				return this->_hWindow;
			}
		protected:		// 外部から set 不可。set は必ず Window::set() と連動する。
			void set( IntPtr hWindow )
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
				this->_hWindow = hWindow;
			}
		}
		property DWORD dwMediaSessionスレッドID
		{
			DWORD get()
			{
				this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
				return this->_dwMediaSessionスレッドID;
			}
		}
		property CAtom<bool>^ bアプリケーションを終了する;		// Run() 内で初期化。

		// コンストラクタ、ディスポーザ、ファイナライザは使わず、Run() の中で全部完結させる。

		CApplicationBase()
		{
			this->Disposed = gcnew CDisposed();

			this->_Window = nullptr;
			this->_hWindow = IntPtr::Zero;
			this->_dwMediaSessionスレッドID = 0;
		};
		~CApplicationBase() 
		{
			if( this->Disposed->bDispose済みまたは処理中である )
				return;		// 例外は発出しない。

			if( !this->Disposed->t開始を宣言する() )
				return;		// 例外は発出しない。


			//GC::SuppressFinalize( this );   --> コンパイラが勝手にやる
		};
		//!CApplicationBase() {};		使わないファイナライザは書かない。書くと GC で管理されるので重くなる。


		// メインエントリ

		void Run();

	protected:

		// アプリケーションを構成する CActivity ツリーのトップレベルの CActivity のリスト。
		// 登録・削除は派生クラスで行うこと。
		property List<CActivity^>^ listトップレベルActivities;

		// On描画()の後にPresent()を行うか否かを指定する。
		// 例えば、Direct3Dデバイスの切替え中にはPresentは停止しなければならない。
		property CAtom<bool>^ bPresentスキップ;

		virtual bool On初期化()
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
			return true;			// false を返すか例外を出すとアプリ終了。
		}
		virtual void On終了()
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
		}
		virtual void Onフロー制御()
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
		}
		virtual bool On進行()
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
			return !this->bアプリケーションを終了する->Get();
		}
		virtual void On描画前()
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
		}
		virtual void On描画( IntPtr hDevice )
		{
			this->Disposed->tDispose済みまたは実行中なら例外発生( "CApplicationBase" );
		}
		
		void On全デバイスリソースの作成();
		void On全デバイスリソースの解放();
		
		void tフロー制御スレッド処理();
		void t進行スレッド処理();
		void t描画スレッド処理();
		void tMediaSessionスレッド処理();

	private:
		CDisposed^ Disposed;

		CWindow^ _Window;
		IntPtr _hWindow;
		DWORD _dwMediaSessionスレッドID;

		void Window_FormClosed( Object^ sender, FormClosedEventArgs^ e );
	};
}
