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

namespace StrokeStyleT
{
	/// <summary>
	/// 全ユーザで共通のシステム設定。
	/// </summary>
	class Config : IDisposable
	{
		public int nSoundバッファ長ms
		{
			get
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					return this._nSoundバッファ長ms;
				}
			}
			set
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					this._nSoundバッファ長ms = value;
				}
			}
		}
		public int nSound更新間隔ms
		{
			get
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					return this._nSound更新間隔ms;
				}
			}
			set
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					this._nSound更新間隔ms = value;
				}
			}
		}
		public PadAssign PadAssign
		{
			get
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					return this._PadAssign;
				}
			}
			set
			{
				lock( this )
				{
					this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );
					this._PadAssign = value;
				}
			}
		}

		public void Load( string stgConfigファイルパスマクロ無し )
		{
			lock( this )
			{
				this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );

				if( !File.Exists( stgConfigファイルパスマクロ無し ) )
					return;

				var reader = new XmlTextReader( new StreamReader( stgConfigファイルパスマクロ無し ) );

				try
				{
					string attrib = null;

					while( reader.Read() )
					{
						if( reader.NodeType == XmlNodeType.EndElement && reader.Name.Equals( "Configuration" ) )
							break;

						if( reader.NodeType == XmlNodeType.Element )
						{
							switch( reader.Name )
							{
								case "Sound":
									attrib = reader.GetAttribute( "Buffer" );
									this._nSoundバッファ長ms = ( string.IsNullOrEmpty( attrib ) ) ? 0 : int.Parse( attrib );
									attrib = reader.GetAttribute( "UpdatePeriod" );
									this._nSound更新間隔ms = ( string.IsNullOrEmpty( attrib ) ) ? 0 : int.Parse( attrib );
									break;

								case "PadAssign":
									this._PadAssign.Load( reader );
									break;
							}
						}
					}
				}
				finally
				{
					reader.Close();
				}
			}
		}
		public void Save( string stgConfigファイルパスマクロ無し )
		{
			lock( this )
			{
				this.Disposed.tDispose済みまたは実行中なら例外発生( "Config" );

				var writer = new XmlTextWriter( new StreamWriter( stgConfigファイルパスマクロ無し ) );

				try
				{
					writer.Formatting = Formatting.Indented;

					// <Configuration>

					writer.WriteStartDocument();
					writer.WriteStartElement( null, "Configuration", null );

					// <Sound>

					writer.WriteStartElement( null, "Sound", null );
					writer.WriteAttributeString( "Buffer", this._nSoundバッファ長ms.ToString() );
					writer.WriteAttributeString( "UpdatePeriod", this._nSound更新間隔ms.ToString() );
					writer.WriteEndElement();

					// <PadAssign>

					this._PadAssign.Save( writer );

					// </Configuration>

					writer.WriteEndElement();
					writer.WriteEndDocument();
				}
				finally
				{
					writer.Close();
				}
			}
		}

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

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

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

					if( null == this._PadAssign )
					{
						this._PadAssign.Dispose();
						this._PadAssign = null;
					}
				}

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

		private readonly CDisposed Disposed = new CDisposed();

		private int _nSoundバッファ長ms = 20;
		private int _nSound更新間隔ms = 5;
		private PadAssign _PadAssign = new PadAssign();
	}
}
