using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using FDK;

namespace StrokeStyleT
{
	class Folders : IDisposable
	{
		public string stgシステムフォルダパス
		{
			get
			{
				lock( this )
				{
					return this._stgシステムフォルダパス;
				}
			}
			private set
			{
				lock( this )
				{
					this._stgシステムフォルダパス = value;
				}
			}
		}
		public string stgユーザ共通フォルダパス
		{
			get
			{
				lock( this )
				{
					return this._stgユーザ共通フォルダパス;
				}
			}
			private set
			{
				lock( this )
				{
					this._stgユーザ共通フォルダパス = value;
				}
			}
		}
		public string stgユーザ個別フォルダパス
		{
			get
			{
				lock( this )
				{
					return this._stgユーザ個別フォルダパス;
				}
			}
			private set
			{
				lock( this )
				{
					this._stgユーザ個別フォルダパス = value;
				}
			}
		}

		public Folders()
		{
			// システムフォルダパスの設定

			this._stgシステムフォルダパス = Path.GetDirectoryName( Application.ExecutablePath );

			if( !Directory.Exists( Path.Combine( this._stgシステムフォルダパス, @"Images" ) ) ||
				!Directory.Exists( Path.Combine( this._stgシステムフォルダパス, @"Sounds" ) ) )
			{
				// これらのフォルダが exe と同じ場所にない場合は Visual Studio からの起動であるとみなす。
				this._stgシステムフォルダパス = Path.GetFullPath( Path.Combine( this._stgシステムフォルダパス, @"..\..\..\Package" ) );
			}

			// ユーザ共通フォルダパスの設定

			this._stgユーザ共通フォルダパス = Path.Combine( this._stgシステムフォルダパス, @"Configs" );
			
			if( !Directory.Exists( this._stgユーザ共通フォルダパス ) )
				Directory.CreateDirectory( this._stgユーザ共通フォルダパス );		// 存在しなければ作成する。


			// ユーザ個別フォルダパスの設定

			this._stgユーザ個別フォルダパス = null;	// ログインするまで不明。
		}
		public void Dispose()
		{
		}

		public void tフォルダがなければ作成する( string path )
		{
			// lock(this) 不要

			if( !Directory.Exists( path ) )
				Directory.CreateDirectory( path );
		}
		public string tパスの正当性を確認のうえ絶対パスに変換して返す( string path, string str相対パス時のルート = null )
		{
			// lock(this) 不要

			// path が 空文字列 or null の場合は空文字列を返す。

			if( string.IsNullOrEmpty( path ) )
				return "";


			// path が相対パス指定であれば、引数 str相対パス時のルートからの相対パスと見なす。

			try
			{
				if( !Path.IsPathRooted( path ) )
				{
					if( string.IsNullOrEmpty( str相対パス時のルート ) )
						throw new NullReferenceException( string.Format( "相対パスですがルートパスが指定されていません。[{0}]", this.tファイルパスをマクロ付きパスに変換する( path ) ) );

					path = Path.Combine( str相対パス時のルート, path );
				}
			}
			catch( ArgumentException e )
			{
				throw new ArgumentException( string.Format( "パス文字列に無効な文字が含まれています。[{0}]", this.tファイルパスをマクロ付きパスに変換する( path ) ), e );
			}


			// path 文字列がパスとして正しいかを個別確認する。

			try
			{
				path = Path.GetFullPath( path );	// path は既に絶対パスになっているが、Path.GetFullPath() を利用して、パス文字列の正当性確認を行う。
			}
			catch( ArgumentException e )
			{
				throw new ArgumentException( string.Format( "パス文字列に無効な文字が含まれています。[{0}]", path ), e );
			}
			catch( System.Security.SecurityException e )
			{
				throw new System.Security.SecurityException( string.Format( "パスにはアクセス権限がありません。[{0}]", path ), e );
			}
			catch( NotSupportedException e )
			{
				throw new NotSupportedException( string.Format( "パス文字列にサポートされていない文字が含まれています。[{0}]", path ), e );
			}
			catch( PathTooLongException e )
			{
				throw new PathTooLongException( string.Format( "パス文字列が長すぎます。[{0}]", path ), e );
			}

			return path;
		}
	
		// パスを表示・出力する場合は、マクロ付きパスに変換してユーザ名などを隠蔽すること。

		public string tファイルパスをマクロ付きパスに変換する( string path )
		{
			this.tファイルパスをマクロ付きパスに変換する( ref path );
			return path;
		}
		public void tファイルパスをマクロ付きパスに変換する( ref string path )
		{
			lock( this )
			{
				// システムフォルダ

				path = path.Replace( this._stgシステムフォルダパス, @"$(SystemFolder)" );


				// ユーザ共通フォルダ

				path = path.Replace( this._stgユーザ共通フォルダパス, @"$(CommonUserFolder)" );


				// ユーザ個別フォルダ

				if( !string.IsNullOrEmpty( this._stgユーザ個別フォルダパス ) )
					path = path.Replace( this._stgユーザ個別フォルダパス, @"$(UserFolder)" );
			}
		}

		public string tファイルパス内のマクロを展開する( string path )
		{
			this.tファイルパス内のマクロを展開する( ref path );
			return path;
		}
		public void tファイルパス内のマクロを展開する( ref string path )
		{
			lock( this )
			{
				// システムフォルダ

				path = path.Replace( @"$(SystemFolder)", this._stgシステムフォルダパス );


				// ユーザ共通フォルダ

				path = path.Replace( @"$(CommonUserFolder)", this._stgユーザ共通フォルダパス );


				// ユーザ個別フォルダ

				if( !string.IsNullOrEmpty( this._stgユーザ個別フォルダパス ) )
					path = path.Replace( @"$(UserFolder)", this._stgユーザ個別フォルダパス );
			}
		}

		private string _stgシステムフォルダパス;
		private string _stgユーザ共通フォルダパス;
		private string _stgユーザ個別フォルダパス;
	}
}
