
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using FDK;

namespace StrokeStyleT
{
	class Theme : IDisposable
	{
		// 固定値！ テーマのサイズを変更する場合はこれも変更すること！
		public static readonly Size sz描画サイズ原寸px = new Size( 1920, 1080 );
		public static readonly int n画面下端からヒットバー中央までの距離px = 173;
		
		public static PointF t2DXYto3DXY( Point pt2D )
		{
			//this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );		static なのでノーチェック

			return new PointF(
				pt2D.X - ( Theme.sz描画サイズ原寸px.Width / 2.0f ),
				( Theme.sz描画サイズ原寸px.Height - pt2D.Y ) - ( Theme.sz描画サイズ原寸px.Height / 2.0f ) );
		}

		public DisplayMode dm現在の表示モード
		{
			get
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );
					return this._dm現在の表示モード;
				}
			}
			private set
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );
					this._dm現在の表示モード = value;
				}
			}
		}
		public List<DisplayMode> list現在のデスクトップフォーマットに対応する表示モードのリスト
		{
			get
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );
					return this._list現在のデスクトップフォーマットに対応する表示モードのリスト;
				}
			}
			private set
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );
					this._list現在のデスクトップフォーマットに対応する表示モードのリスト = value;
				}
			}
		}

		public Theme( IntPtr hWindow )
		{
			// 現在のデスクトップフォーマット、ならびにそのフォーマットに対応する全表示モードの取得。

			this._dm現在の表示モード = Global.Direct3D.t現在のディスプレイモードを取得する();
			this._list現在のデスクトップフォーマットに対応する表示モードのリスト = Global.Direct3D.tフォーマットに対応するディスプレイモードを取得する( hWindow, this._dm現在の表示モード.Format );
		}

		#region [ Dispose-Finalize パターン ]
		//-------------------------
		public void Dispose()
		{
			if( this.Disposed.bDispose済みまたは処理中である )
				return;		// 例外を発出させない。

			if( !this.Disposed.t開始を宣言する() )
				return;		// 例外を発出させない。

			this.Dispose( true );
			GC.SuppressFinalize( this );
		}
		//~Theme() { this.Dispose( false ); }		Unmanaged がないのでファイナライザは無し
		protected void Dispose( bool bReleaseManaged )
		{
			if( bReleaseManaged )
			{
				// TODO: ここで Managed を解放する

				this._list現在のデスクトップフォーマットに対応する表示モードのリスト.Clear();
			}

			// TODO: ここで Unmanaged を解放する
		}
		//-------------------------
		#endregion

		/// <summary>
		/// 現在の表示モードに最適なクライアントサイズを返す。
		/// （クライアントサイズの候補は Theme.cs にハードコーティングされている。）
		/// </summary>
		public Size t現在の表示モードに最適なクライアントサイズを取得する( CWindow form )
		{
			lock( this )
			{
				this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );

				Debug.Assert( ( 0 < this._dm現在の表示モード.Width ) && ( 0 < this._dm現在の表示モード.Height ) );


				// 大きいクライアントサイズから順番にチェックしていく。

				foreach( var sz候補 in arrsz許容ウィンドウクライアントサイズ一覧 )
				{
					if( this.b現在の表示モードでウィンドウをはみ出さずに可能である( form, sz候補 ) )
						return sz候補;
				}


				// 普通なら、ここにくることはないだろうが……

				throw new Exception( "許容可能なクライアントサイズが存在しません。" );
			}
		}

		private bool b現在の表示モードでウィンドウをはみ出さずに可能である( CWindow window, Size sz想定するクライアントサイズ )
		{
			//this.Disposed.tDispose済みまたは実行中なら例外発生( "Theme" );		private なのでノーチェック。
			
			Debug.Assert( ( 0 < this.dm現在の表示モード.Width ) && ( 0 < this.dm現在の表示モード.Height ) );

			Size sz想定されるウィンドウサイズ = window.tクライアントサイズからウィンドウサイズを計算して返す( sz想定するクライアントサイズ );
			return ( ( sz想定されるウィンドウサイズ.Width <= this._dm現在の表示モード.Width ) && ( sz想定されるウィンドウサイズ.Height <= this._dm現在の表示モード.Height ) );
		}

		private readonly Size[] arrsz許容ウィンドウクライアントサイズ一覧 = new Size[]
		{
			#region [ 16:9 のサイズを集めてみた。大きい順に並べてある。]
			//-------------------------
			new Size( 1920, 1080 ),	// SSTでの画像のピクセル原寸
			new Size( 1600, 900 ),
			new Size( 1280, 720 ),
			new Size( 1024, 576 ),
			new Size( 960, 540 ),
			new Size( 640, 360 ),
			new Size( 427, 240 ),	// これより下はないだろう。
			//-------------------------
			#endregion
		};

		private readonly CDisposed Disposed = new CDisposed();

		private DisplayMode _dm現在の表示モード;
		private List<DisplayMode> _list現在のデスクトップフォーマットに対応する表示モードのリスト;
	}
}
