// <summary>ソースコード：>ＨＹＳＳＯＰ環境情報管理クラス</summary>
// <author>CommonMP</author>

using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

using CommonMP.HYSSOP.Interface;
using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.Interface.HSTools;
using CommonMP.HYSSOP.Interface.HSController;
using CommonMP.HYSSOP.CoreImpl.HSData;

namespace CommonMP.HYSSOP.CoreImpl.HSTools
{
    /// <summary><para>class outline:</para>
    /// <para>環境情報管理クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP]
    /// [ver 1.0.0][2008/10/01][新規作成]
    /// [ver 1.1.0][2010/12/06] データホームディレクトリ関係追加
    /// </para>
    /// </remarks>
    public class HySEnvInf : HySRoot
    {
        /// <summary>アプリケーションホームディレクトリ(Execute)</summary>
        static private HySString m_csHomeDirectory = null;
        
        /// <summary>CommonMPデータホームディレクトリ </summary>
        static private HySString m_csDataDirectory = null;

        /// <summary>環境ファイル名称</summary>
        static private HySString m_csEnvFileName = null;

        /// <summary>環境ファイル検索パス</summary>
        static private readonly HySString ENVFILE_PATH = new HySString("\\conf\\");

        /// <summary>環境ファイル検索パス</summary>
        static private readonly HySString DATA_IN_FILE = new HySString("CommonMPData.ini");

        /// <summary>環境変数を管理するハッシュテーブル  </summary>
        static protected Hashtable m_csEnvInfTable = new Hashtable(); 

        /// <summary>ログクラス</summary>
        static protected HySLog m_csLog=null;

        /// <summary>環境ファイルクラス</summary>
        static protected HySFile m_File = null;

        ///// <summary>乱数</summary>
        //static protected Random m_cRandom = new System.Random();

        /// <summary>カルチャ用参照ディレクトリ</summary>
        static private HySString m_csCultureDirectory = new HySString("");

        /// <summary>データホームディレクトリ履歴</summary>
        static private List<KeyValuePair<int, string>> csDataHomeList = new List<KeyValuePair<int, string>>();

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf csEnvInf = HySEnvInf(csEnvFileName)</para>
        /// </example>
        /// <param name="csEnvFileName">環境ファイル名称</param>
        /// <returns>HySEnvInf  生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySEnvInf(HySString csEnvFileName)
        {
            m_csEnvFileName = csEnvFileName;
            // アプリケーションホームディレクトリを設定
            DirectoryInfo csDi = Directory.GetParent(Directory.GetCurrentDirectory());
            m_csHomeDirectory = new HySString(csDi.ToString());

            // カルチャ判定
            if (System.Threading.Thread.CurrentThread.CurrentUICulture.Name.StartsWith("en") == true)
            {// 英語
                //m_csCultureDirectory = new HySString("en\\");
            }
            //else if (System.Threading.Thread.CurrentThread.CurrentUICulture.Name.StartsWith("ja") == true)
            //{// 日本語
            //    m_csCultureDirectory = new HySString("ja\\");
            //}
            else
            {
                string sCulturename = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
                string sDirpath = m_csHomeDirectory.ToString() + ENVFILE_PATH.ToString() + sCulturename;
                if (Directory.Exists(sDirpath))
                {
                    m_csCultureDirectory = new HySString(sCulturename + "\\");
                }
            }

            // ホームディレクトリ取得処理
            m_csDataDirectory = GetDataDirectory();

            // ホームディレクトリ履歴読み込み
            ReadDataHomeHistory();

            m_csEnvInfTable.Clear();
        }

        /// <summary><para>method outline:</para>
        /// <para>ホームディレクトリ取得処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetDataDirectory() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString  ホームディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>[CommonMP][ver 1.6.0][2016/02/15][新規作成]</para>
        /// </remarks>
        static public HySString GetDataDirectory()
        {
            HySString csDataHomeIniFileName = m_csHomeDirectory + ENVFILE_PATH + DATA_IN_FILE;
            HySIniFile csIniFile = new HySIniFile(csDataHomeIniFileName);
            HySString csDataPath = csIniFile.GetValue(new HySString("DATAHOME"));
            HySString csDataDirectory = null;
            if ((object)csDataPath != null)
            {// 環境定義取得
                if (Path.IsPathRooted(csDataPath.ToString()) == true)
                {// 絶対パス
                    csDataDirectory = csDataPath.Clone();
                }
                else
                {// 相対パス
                    csDataDirectory = m_csHomeDirectory + "\\" + csDataPath;
                }
            }
            else
            {// 環境定義無し
                // CommonMP\CommonMPDataをデフォルトフォルダとする。
                int iCase = m_csHomeDirectory.ToString().LastIndexOf("CommonMP\\");
                if (iCase > 0)
                {// CommonMPフォルダー有り
                    csDataDirectory = new HySString(m_csHomeDirectory.ToString().Substring(0, iCase + 9)) + new HySString("CommonMPData");
                }
                else
                {// CommonMPフォルダー無し
                    csDataDirectory = m_csHomeDirectory + new HySString("\\..\\CommonMPData");
                }
            }

            return new HySString(Path.GetFullPath(csDataDirectory.ToString()));
        }

        /// <summary><para>method outline:</para>
        /// <para>環境変数の読み込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csEnvInf = HySEnvInf.GetEnvInf(csKeyName)</para>
        /// </example>
        /// <param name="csKeyName">キー名称</param>
        /// <returns>HySString  環境データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public HySString GetEnvInf(HySString csKeyName)
        {
            return (HySString)m_csEnvInfTable[csKeyName.ToString()];
        }
        /// <summary><para>method outline:</para>
        /// <para>環境変数の読み込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csEnvInf = HySEnvInf.GetEnvInf(sKeyName)</para>
        /// </example>
        /// <param name="sKeyName">キー名称</param>
        /// <returns>環境データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public HySString GetEnvInf(string sKeyName)
        {
            return (HySString)m_csEnvInfTable[sKeyName];
        }

        /// <summary><para>method outline:</para>
        /// <para>初期化処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Initialize() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long =0:正常  =-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long Initialize()
        {
            // =======環境情報読み込み====
            if (LoadEnvFile() < 0)
            {
                return -1;
            }

            // =======ログ管理クラス作成=====
            DateTime csNowDate = DateTime.Now;
            // ログレベルを環境から取得
            HySString csLogLevel = HySEnvInf.GetEnvInf(new HySString("LOG_LEVEL"));
            long LogLevel = HySLog.TRIAL_RUN;
            if ((object)csLogLevel != null)
            {
                if (csLogLevel.ToString() == "ONLINE")
                {
                    LogLevel = HySLog.ONLINE;
                }
                else if (csLogLevel.ToString() == "TRIAL_RUN")
                {
                    LogLevel = HySLog.TRIAL_RUN;
                }
                else if (csLogLevel.ToString() == "DEBUG")
                {
                    LogLevel = HySLog.DEBUG;
                }
                else if (csLogLevel.ToString() == "SYSTEM_DEBUG")
                {
                    LogLevel = HySLog.SYSTEM_DEBUG;
                }
            }

            // ログ出力クラス生成
            m_csLog = new HySLog(LogLevel);

            // 環境ファイルから取得
            bool bSetSysCslDisp = false;
            HySString csEnvRtn = HySEnvInf.GetEnvInf(new HySString("CONSOLE_LOG_OUT"));
            if( (object)csEnvRtn != null )
            {
                bSetSysCslDisp = csEnvRtn.Equal(new HySString("TRUE"));
            }
            m_csLog.SetSysCslDisp(bSetSysCslDisp);

            bool bSetFileOutFlg = false;
            csEnvRtn = HySEnvInf.GetEnvInf(new HySString("FILE_LOG_OUT"));
            if( (object)csEnvRtn != null )
            {
                bSetFileOutFlg = csEnvRtn.Equal(new HySString("TRUE"));
            }
            m_csLog.SetFileOutFlg(bSetFileOutFlg);

            // ログ立ち上がり
            m_csLog.WakeUp();
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>初期化処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> InitializeNoLog() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long =0:正常  =-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long InitializeNoLog()
        {
            // =======環境情報読み込み====
            if (LoadEnvFile() < 0)
            {
                return -1;
            }
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>終了処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf.Terminate() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void Terminate()
        {
            m_csLog.ShutDown();
        }

        /// <summary><para>method outline:</para>
        /// <para>環境変数の読み込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lRtn = LoadEnvFile() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long　=0:正常、=-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected long LoadEnvFile()
        {
            HySString csReadStr;            // 読み取りデータ
            HySString csFileName;           // 環境設定ファイル名称
            String csVarName;               // 変数名
            String csValName;               // 変数値
            long lFirstTabPos = 0;          // 最初のタブ文字位置
            long lSecondTabPos = 0;         // 二番目のタブ文字位置
            long lEqualPos = 0;             // イコール文字位置

            // 管理テーブルのクリア
            m_csEnvInfTable.Clear();

            //csFileName = m_csHomeDirectory + ENVFILE_PATH + m_csEnvFileName;
            csFileName = m_csHomeDirectory + ENVFILE_PATH + m_csCultureDirectory + m_csEnvFileName;

            m_File = new HySFile(csFileName);

            if (m_File.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) != 0)  // 環境設定ファイルが開けない
            {
                m_File = null;
                HySFile csErrFile = new HySFile(HySEnvInf.sErorrFileName);
                if (csErrFile.Exist() == true)
                {
                    csErrFile.Open(HySFile.OPEN_MODE.APPEND, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
                }
                else
                {
                    csErrFile.Open(HySFile.OPEN_MODE.OPEN_OR_CREAT, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
                }
                csErrFile.WriteText("Cannot open file. (" + csFileName.ToString() + ")" );
                csErrFile.Close();
                return -1;
            }

            csReadStr = new HySString("");
            while (m_File.ReadText(ref csReadStr) != 0)       // ファイルの最後まで
            {
                // 前項情報の初期化
                lFirstTabPos = 0;
                lSecondTabPos = 0;
                lEqualPos = 0;

                if (csReadStr.ToString().IndexOf("#") == 0 || csReadStr.ToString() == String.Empty) // コメント文、空行読み飛ばし
                {
                    continue;
                }

                // 二つのタブ、イコール文字の位置を探す
                lFirstTabPos = csReadStr.ToString().IndexOf("\t");
                lSecondTabPos = csReadStr.ToString().IndexOf("\t", (int)lFirstTabPos + 1);
                lEqualPos = csReadStr.IndexOf("=");

                if (lFirstTabPos == 0 || lSecondTabPos == 0)    // 書式エラー読み飛ばし
                {
                    continue;
                }

                if (lFirstTabPos > lEqualPos || lSecondTabPos < lEqualPos)  // 書式エラー読み飛ばし
                {
                    continue;
                }

                // 変数名読み取り
                csVarName = csReadStr.ToString().Substring(0, (int)lFirstTabPos);

                // 変数値読み取り
                csValName = csReadStr.ToString().Substring((int)lSecondTabPos + 1);

                if (csVarName.Length > 0 && csValName.Length > 0)   // 変数取得確認
                {
                    m_csEnvInfTable.Add(csVarName, new HySString(csValName));
                }
            }
            m_File.Close();
            m_File = null;

            return 0;
        }

        # region 削除
        ///// <summary><para>method outline:</para>
        ///// <para>ユニークＩＤの生成</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para> HySID csUniqueID = CreateUniqueID() </para>
        ///// </example>
        ///// <param name="">無し</param>
        ///// <returns>csID　ユニークＩＤ</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para>無し</para>
        ///// </remarks>
        //static public HySID CreateUniqueID()
        //{
        //    // 仮処理
        //    long lNum = m_cRandom.Next(1000);
        //    HySID csID = new HySID(DateTime.Now.ToString() + lNum.ToString() + "."+ ""+ "");
        //    return csID;
        //}
        # endregion

        
        /// <summary><para>method outline:</para>
        /// <para>アプリケーションホームディレクトリ手動設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf.SetHomeDirectory(csHomeDirectory)</para>
        /// </example>
        /// <param name="csHomeDirectory">ホームディレクトリ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void SetHomeDirectory(HySString csHomeDirectory)
        {
            m_csHomeDirectory = csHomeDirectory;
        }
        /// <summary><para>method outline:</para>
        /// <para>CommonMPデータホームディレクトリ手動設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf.SetDataHomeDirectory(csDataHomeDirectory)</para>
        /// </example>
        /// <param name="csDataHomeDirectory">CommonMPデータホームディレクトリ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void SetDataHomeDirectory(HySString csDataHomeDirectory)
        {
            m_csDataDirectory = csDataHomeDirectory;
        }

        /// <summary><para>method outline:</para>
        /// <para>CommonMPデータホームディレクトリ履歴保存</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf.SaveDataHomeHistory() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>[CommonMP][ver 1.6.0][2016/02/15][新規作成]</para>
        /// </remarks>
        static public void SaveDataHomeHistory()
        {
            HySString csDataHomeIniFileName = m_csHomeDirectory + ENVFILE_PATH + DATA_IN_FILE;
            HySIniFile csIniFile = new HySIniFile(csDataHomeIniFileName);

            // 現在設定されているデータホーム
            HySString csDataPath = HySEnvInf.GetDataDirectory();

            // 起動時のデータホーム
            m_csDataDirectory = new HySString(Path.GetFullPath(m_csDataDirectory.ToString()));

            // 起動時と終了時のデータホームを比較
            if (m_csDataDirectory.CompareTo(csDataPath) != 0)
            {
                csIniFile.SetValue(new HySString("DATAHOME01"), m_csDataDirectory, true);

                int key = 2;
                int index = 1;
                HySString csDataHome = null;

                foreach (KeyValuePair<int, string> pair in csDataHomeList)
                {
                    if (key == 20)
                    {
                        // 履歴登録は１９件まで
                        break;
                    }
                    if (pair.Key.Equals(index))
                    {
                        csDataHome = new HySString("DATAHOME") + (key).ToString("00");
                        if (csDataPath.CompareTo(new HySString(pair.Value)) != 0)
                        {
                            // 履歴内で重複はしない
                            csIniFile.SetValue(csDataHome, new HySString(pair.Value), true);
                            key++;
                        }
                        index++;
                    }
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>CommonMPデータホームディレクトリ履歴読み込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySEnvInf.ReadDataHomeHistory() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>[CommonMP][ver 1.6.0][2016/02/15][新規作成]</para>
        /// </remarks>
        private void ReadDataHomeHistory()
        {
            HySString csDataHomeIniFileName = m_csHomeDirectory + ENVFILE_PATH + DATA_IN_FILE;
            HySIniFile csIniFile = new HySIniFile(csDataHomeIniFileName);
            KeyValuePair<int, string> pair;
            HySString csDataHome = null;
            HySString csHistory = null;

            // データホームディレクトリ履歴
            csDataHomeList.Clear();

            for (int i = 1; i < 20; i++)
            {
                csDataHome = new HySString("DATAHOME") + i.ToString("00");
                csHistory = csIniFile.GetValue(csDataHome);

                if ((object)csHistory == null)
                {
                    break;
                }

                // データホームディレクトリ履歴構築
                pair = new KeyValuePair<int, string>(i, csHistory.ToString());
                csDataHomeList.Add(pair);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>CommonMPデータホームディレクトリ履歴取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string value = HySEnvInf.GetDataHomeHistory() </para>
        /// </example>
        /// <param name="index">インデックス</param>
        /// <returns>HySString  ディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>[CommonMP][ver 1.6.0][2016/02/15][新規作成]</para>
        /// </remarks>
        static public string GetDataHomeHistory(int index)
        {
            HySString csDataPath = new HySString("DATAHOME");

            csDataPath += index.ToString("00");

            foreach (KeyValuePair<int, string> pair in csDataHomeList)
            {
                if (pair.Key.Equals(index))
                {
                    return (pair.Value);
                }
            }

            return null;
        }

        #region 便利ツール群

        /// <summary><para>method outline:</para>
        /// <para>アプリケーションホームディレクトリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csHomeDirectory = HySEnvInf.GetHomeDirectory()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString  アプリケーションホームディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>アプリケーションホームディレクトリを返す</para>
        /// </remarks>
        static public HySString GetHomeDirectory()
        {
            return m_csHomeDirectory;
        }

        /// <summary><para>method outline:</para>
        /// <para>CommonMPデータホームディレクトリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csDataHomeDirectory = HySEnvInf.GetDataHomeDirectory()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString  CommonMPデータホームディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>CommonMPのデータホームディレクトリを返す</para>
        /// </remarks>
        static public HySString GetDataHomeDirectory()
        {
            return m_csDataDirectory;
        }

        /// <summary><para>method outline:</para>
        /// <para>ＤＢ用ホームディレクトリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csDBDirectory = HySEnvInf.GetDBDirectory()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString  ＤＢ用ホームディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// ＤＢ用のホームディレクトリを返す
        /// 例えばＤＢを別ＨＤＤ等で管理する場合に使用.
        /// 
        /// CommonMP.cfg ファイル内に　
        /// 　MCDBA_HOME_PATH	=	F:@\DBFolderr
        /// の様に定義されている場合、その値を返す。
        /// 定義無しの場合は、HySEnvInf.GetHomeDirectory()と同じ値を返す
        /// </para>
        /// </remarks>
        static public HySString GetDBDirectory()
        {
            HySString csDBDir = (HySString)m_csEnvInfTable[MCDBA_HOME_PATH];
            if ((object)csDBDir == null)
            {
                csDBDir = GetHomeDirectory();
            }

            return csDBDir;
        }


        /// <summary><para>method outline:</para>
        /// <para>カルチャディレクトリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csCultureDirectory = GetCultureDirectory()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString  カルチャディレクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>アプリケーション実行時に取得したカルチャディレクトリを返す</para>
        /// </remarks>
        static public HySString GetCultureDirectory()
        {
            return m_csCultureDirectory;
        }

        #endregion

        /// <summary>ログ起動前のエラーファイル名 </summary>
        public static readonly string sErorrFileName = "..\\log\\CommonMPERROR.txt";
        /// <summary>ＤＢ関連ホームディレクトリ </summary>
        public static readonly string MCDBA_HOME_PATH = "MCDBA_HOME_PATH"; 
    }
}
