using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Diagnostics;

namespace DTXMania
{
	public class CSetDef
	{
		// プロパティ

		public List<CBlock> blocks;
		public class CBlock
		{
			/// <summary>
			/// このブロックが有効である（何かのプロパティがセットされた）場合、true を示す。
			/// </summary>
			public bool b使用中 { get; set; }

			/// <summary>
			/// スコアファイル名（#LxFILE）を保持する。配列は [0～4] で、存在しないレベルは null となる。
			/// </summary>
			public string[] File
			{
				get
				{
					return this._file;
				}
				set						// ここには来ない( Label[xx] にsetすると、結局Labelのgetが呼ばれるだけで、Labelのsetは呼ばれない)
				{
					this._file = value;
					this.b使用中 = true;
				}
			}

			/// <summary>
			/// スコアのフォント色（#FONTCOLOR）を保持する。
			/// </summary>
			public Color FontColor
			{
				get
				{
					return this._fontcolor;
				}
				set
				{
					this._fontcolor = value;
					this.b使用中 = true;
				}
			}

			/// <summary>
			/// スコアのジャンル名を保持する。（現在は使われていない。）
			/// </summary>
			public string Genre
			{
				get
				{
					return this._genre;
				}
				set
				{
					this._genre = value;
					this.b使用中 = true;
				}
			}

			/// <summary>
			/// スコアのラベル（#LxLABEL）を保持する。配列は[0～4] で、存在しないレベルは null となる。
			/// </summary>
			public string[] Label
			{
				get
				{
					return this._label;
				}
				set						// ここには来ない( Label[xx] にsetすると、結局Labelのgetが呼ばれるだけで、Labelのsetは呼ばれない)
				{
					this._label = value;
					this.b使用中 = true;
				}
			}

			/// <summary>
			/// スコアのタイトル（#TITLE）を保持する。
			/// </summary>
			public string Title
			{
				get
				{
					return this._title;
				}
				set
				{
					this._title = value;
					this.b使用中 = true;
				}
			}

			#region [ private ]
			//-----------------
			private string[] _file = new string[ 5 ];
			private Color _fontcolor = Color.White;
			private string _genre = "";
			private string[] _label = new string[ 5 ];
			private string _title = "";
			//-----------------
			#endregion
		}


		// コンストラクタ

		public CSetDef()
		{
			this.blocks = new List<CBlock>();
		}
		public CSetDef( string setdefファイル名 )
			: this()
		{
			this.t読み込み( setdefファイル名 );
		}


		// メソッド

		public void t読み込み( string setdefファイル名 )
		{
			var reader = new StreamReader( setdefファイル名, Encoding.GetEncoding( "Shift_JIS" ) );
			CBlock block = new CBlock();
			string str = null;
			while( ( str = reader.ReadLine() ) != null )
			{
				if( str.Length != 0 )
				{
					try
					{
						str = str.TrimStart( new char[] { ' ', '\t' } );
						if( ( str.Length > 0 ) && ( str[ 0 ] == '#' ) && ( str[ 0 ] != ';' ) )
						{
							if( str.IndexOf( ';' ) != -1 )
							{
								str = str.Substring( 0, str.IndexOf( ';' ) );
							}
							if( str.StartsWith( "#TITLE", StringComparison.OrdinalIgnoreCase ) )
							{
								if( block.b使用中 )
								{
									this.tFILEの指定があるのにLxLABELが省略されているときはデフォルトの名前をセットする( block );
									this.tLxLABELの指定があるのにFILEが省略されているときはなかったものとする( block );
									this.blocks.Add( block );
									block = new CBlock();
								}
								block.Title = str.Substring( 6 ).TrimStart( new char[] { ':', ' ', '\t' } );
							}
							else if( str.StartsWith( "#FONTCOLOR", StringComparison.OrdinalIgnoreCase ) )
							{
								block.FontColor = ColorTranslator.FromHtml( "#" + str.Substring( 10 ).Trim( new char[] { ':', '#', ' ', '\t' } ) );
							}
							else if( str.StartsWith( "#L1FILE", StringComparison.OrdinalIgnoreCase ) )
							{
								block.File[ 0 ] = str.Substring( 7 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L2FILE", StringComparison.OrdinalIgnoreCase ) )
							{
								block.File[ 1 ] = str.Substring( 7 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L3FILE", StringComparison.OrdinalIgnoreCase ) )
							{
								block.File[ 2 ] = str.Substring( 7 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L4FILE", StringComparison.OrdinalIgnoreCase ) )
							{
								block.File[ 3 ] = str.Substring( 7 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L5FILE", StringComparison.OrdinalIgnoreCase ) )
							{
								block.File[ 4 ] = str.Substring( 7 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L1LABEL", StringComparison.OrdinalIgnoreCase ) )
							{
								block.Label[ 0 ] = str.Substring( 8 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L2LABEL", StringComparison.OrdinalIgnoreCase ) )
							{
								block.Label[ 1 ] = str.Substring( 8 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L3LABEL", StringComparison.OrdinalIgnoreCase ) )
							{
								block.Label[ 2 ] = str.Substring( 8 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L4LABEL", StringComparison.OrdinalIgnoreCase ) )
							{
								block.Label[ 3 ] = str.Substring( 8 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
							else if( str.StartsWith( "#L5LABEL", StringComparison.OrdinalIgnoreCase ) )
							{
								block.Label[ 4 ] = str.Substring( 8 ).Trim( new char[] { ':', ' ', '\t' } );
								block.b使用中 = true;		// #28937 2012.7.7 yyagi; "get" accessor is called for T[] property. So b使用中 is not modified to set the property. I need to update it myself.
							}
						}
						continue;
					}
					catch
					{
						continue;
					}
				}
			}
			reader.Close();
			if( block.b使用中 )
			{
				this.tFILEの指定があるのにLxLABELが省略されているときはデフォルトの名前をセットする( block );
				this.tLxLABELの指定があるのにFILEが省略されているときはなかったものとする( block );
				this.blocks.Add( block );
			}
		}


		// その他

		#region [ private ]
		//-----------------
		private void tFILEの指定があるのにLxLABELが省略されているときはデフォルトの名前をセットする( CBlock block )
		{
			string[] strArray = new string[] { "BASIC", "ADVANCED", "EXTREME", "HYPER", "ULTIMATE" };
			for( int i = 0; i < 5; i++ )
			{
				if( ( ( block.File[ i ] != null ) && ( block.File[ i ].Length > 0 ) ) && string.IsNullOrEmpty( block.Label[ i ] ) )
				{
					block.Label[ i ] = strArray[ i ];
				}
			}
		}
		private void tLxLABELの指定があるのにFILEが省略されているときはなかったものとする( CBlock block )
		{
			for( int i = 0; i < 5; i++ )
			{
				if( ( ( block.Label[ i ] != null ) && ( block.Label[ i ].Length > 0 ) ) && string.IsNullOrEmpty( block.File[ i ] ) )
				{
					block.Label[ i ] = "";
				}
			}
		}
		//-----------------
		#endregion
	}
}
