#pragma once

namespace FDK
{
	public ref class Utils abstract sealed
	{
	public:

		// GC

		static void t完全なガベージコレクションを実施する()
		{
			GC::Collect();					// 1.アクセス不可能なオブジェクトを除去し、ファイナライゼーション実施。
			GC::WaitForPendingFinalizers();	// 2.ファイナライゼーションが終わるまでスレッドを待機。
			GC::Collect();					// 3.ファイナライズされたばかりのオブジェクトのメモリを開放。

			// 参考: http://msdn.microsoft.com/ja-jp/library/ms998547.aspx#scalenetchapt05_topic10
		}


		// ログ

		static void t例外の詳細をログに出力する( Exception^ e )
		{
			Trace::WriteLine( "---例外ここから----" );
			Trace::WriteLine( e->ToString() );
			Trace::WriteLine( "---例外ここまで----" );
		}


		// IO

		static String^ t指定した拡張子を持つファイルを検索し最初に見つけたファイルの絶対パスを返す( String^ strフォルダパス, List<String^>^ list拡張子リスト )
		{
			array<String^>^ files = Directory::GetFiles( strフォルダパス );	// GetFiles() は完全パスを返す。


			// ファイル順より拡張子順を優先して検索する。→ 拡張子リストの前方の拡張子ほど先に発見されるようにするため。

			for each( String^ ext in list拡張子リスト )
			{
				for each( String^ file in files )
				{
					String^ fileExt = Path::GetExtension( file );

					if( fileExt->Equals( ext, System::StringComparison::OrdinalIgnoreCase ) )
						return file;		// あった
				}
			}

			return nullptr;	// なかった
		}


		// XML (参考: http://msdn.microsoft.com/ja-jp/library/vstudio/90c86ass%28v=vs.110%29.aspx )

		generic< class T >
		static void tXMLファイルを読み込む( String^ strXMLファイル名, [Out] T% xmlObject )
		{
			xmlObject = T();

			FileStream^ fs = nullptr;
			StreamReader^ sr = nullptr;
			try
			{
				fs = gcnew FileStream( strXMLファイル名, FileMode::Open, FileAccess::Read, FileShare::ReadWrite );	// FileShare を付けとかないと、Close() 後もロックがかかる。
				sr = gcnew StreamReader( fs, Encoding::UTF8 );
				XmlSerializer^ xmlsl = gcnew XmlSerializer( T::typeid );
				xmlObject = (T) xmlsl->Deserialize( sr );
			}
			finally
			{
				if( sr != nullptr )
					sr->Close();		// fr も一緒にClose()される
			}
		}
		
		generic< class T >
		static void tXMLファイルを保存する( String^ strXMLファイル名, [In] T xmlObject )
		{
			FileStream^ fs = nullptr;
			StreamWriter^ sw = nullptr;
			try
			{
				fs = gcnew FileStream( strXMLファイル名, FileMode::Create, FileAccess::Write, FileShare::ReadWrite );	// FileShare を付けとかないと、Close() 後もロックがかかる。
				sw = gcnew StreamWriter( fs, Encoding::UTF8 );

				XmlSerializer^ xmlsl = gcnew XmlSerializer( T::typeid );
				xmlsl->Serialize( sw, xmlObject );
			}
			finally
			{
				if( sw != nullptr )
					sw->Close();		// fs も一緒にClose()される
			}
		}


		// 数学

		static double DegreeToRadian( double angle )
		{
			return ( ( Math::PI * angle ) / 180.0 );
		}
		static double RadianToDegree( double angle )
		{
			return ( angle * 180.0 / Math::PI );
		}
		static float DegreeToRadian( float angle )
		{
			return (float) DegreeToRadian( (double) angle );
		}
		static float RadianToDegree( float angle )
		{
			return (float) RadianToDegree( (double) angle );
		}
	};
}