// <summary>ソースコード：>ＨＹＳＳＯＰ共通情報ハッシュ管理クラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

using CommonMP.HYSSOP.Interface;
using CommonMP.HYSSOP.Interface.HSData;
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.1.0][2010/12/01][新規作成]</para>
    /// </remarks>
    public class HySCommonInfoHash : HySRoot
    {
//　＝＝＝＝＝＝＝＝＝＝＝＝＝
// 将来　連続稼動システムに向けては、下記を健闘する必要がある。
//  ハッシュ内のデータを蓄積するオブジェクトは、　自らのオブジェクトが不要となった時に、
//  きちんと、保持データを破棄してくれるか？
//  C++での　自オブジェクトのデストラクター処理内で、　RemoveInfo（）をコールに相当する処理を入れる必要がある。
//　＝＝＝＝＝＝＝＝＝＝＝＝＝
        /// <summary>情報管理ハッシュテーブルを管理するハッシュテーブル</summary>
        static protected Hashtable m_csInfoAreaHashTbl = new Hashtable();


        /// <summary><para>method outline:</para>
        /// <para>任意の名前で対象とする対応エリア確保する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> CreateTable(sEreaName) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void CreateTable( string sEreaName )
        {
            m_csInfoAreaHashTbl[sEreaName] = new Hashtable();
        }
        /// <summary><para>method outline:</para>
        /// <para>指定した名称のエリアを削除する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> DeleteTable(sEreaName) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void DeleteTable(string sEreaName)
        {
            m_csInfoAreaHashTbl.Remove(sEreaName);
        }


        /// <summary><para>method outline:</para>
        /// <para>指定エリアに、データを追加する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetCorrespond(sEreaName,sKey, sInfo) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <param name="sKey">キー</param>
        /// <param name="sInfo">データ</param>
        /// <returns>指定エリアが無い時：falseを返す</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool SetCorrespond(string sEreaName, string sKey, string sInfo)
        {
            Hashtable sAreaTbl = m_csInfoAreaHashTbl[sEreaName] as Hashtable;
            if (sAreaTbl != null)
            {
                sAreaTbl[sKey] = sInfo;
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>指定した名称のエリアから、対応する情報を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetCorrespond(sEreaName,sKey, ref sInfo) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <param name="sKey">キー</param>
        /// <param name="sInfo">データ</param>
        /// <returns>指定エリアが無い時：falseを返す</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool GetCorrespond(string sEreaName, string sKey, ref string sInfo)
        {
            Hashtable sAreaTbl = m_csInfoAreaHashTbl[sEreaName] as Hashtable;
            if (sAreaTbl != null)
            {
                sInfo = sAreaTbl[sKey] as string;
                if (sInfo != null)
                {// データ有り
                    return true;
                }
                else
                {// データ無し
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>指定エリアに、データを追加する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetCorrespondData(sEreaName,sKey, sInfo) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <param name="sKey">キー</param>
        /// <param name="csData">データ</param>
        /// <returns>指定エリアが無い時：falseを返す</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool SetCorrespondData(string sEreaName, string sKey, HySRoot csData)
        {
            Hashtable sAreaTbl = m_csInfoAreaHashTbl[sEreaName] as Hashtable;
            if (sAreaTbl != null)
            {
                sAreaTbl[sKey] = csData;
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>指定した名称のエリアから、対応する情報を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySRoot csData = GetCorrespondData(sEreaName,sKey) as HySRoot</para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <param name="sKey">キー</param>
        /// <returns>HySRoot 格納データ（指定エリアが無い時　nullを返す）</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public HySRoot GetCorrespondData(string sEreaName, string sKey)
        {
            HySRoot csData = null;
            Hashtable sAreaTbl = m_csInfoAreaHashTbl[sEreaName] as Hashtable;
            if (sAreaTbl != null)
            {
                csData = sAreaTbl[sKey] as HySRoot;
            }
            return csData;
        }


        /// <summary><para>method outline:</para>
        /// <para>指定した名称のエリアに設定された対応関係を削除する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> RemoveInfo(sEreaName,sKey) </para>
        /// </example>
        /// <param name="sEreaName">エリア名</param>
        /// <param name="sKey">キー</param>
        /// <returns>指定エリアが無い時：falseを返す</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool RemoveInfo(string sEreaName, string sKey)
        {
            Hashtable sAreaTbl = m_csInfoAreaHashTbl[sEreaName] as Hashtable;
            if (sAreaTbl != null)
            {
                sAreaTbl.Remove(sKey);
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>入力されたディレクトリへのパスを指定された基準位置からの相対パスへ変更する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> DirectoryPathExchange(sBasePath,sOriginalPath, ref sRelativePath) </para>
        /// </example>
        /// <param name="sBasePath">基準パス位置</param>
        /// <param name="sOriginalPath">元のパス位置</param>
        /// <param name="sRelativePath">相対パス位置</param>
        /// <returns>変更できないとき：falseを返す</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool DirectoryPathExchange(string sBasePath, string sOriginalPath, ref string sRelativePath)
        {
            // 今のところ未実装
            //    sBasePath ="c:users\base"のとき
            //    sOriginalPath = "c:users\zzz" ならば、 sRelativePathには　"..\zzz" が返る　この時　return true
            //    sOriginalPath = "D:users\zzz" ならば、 sRelativePathには　"" が返る　この時　return false
            //    sOriginalPath = "..\..\zzz" 等で相対化してある場合には何もしない　この時　return true

            bool bRtn = false;      // リターン値

            if (System.IO.Path.IsPathRooted(sOriginalPath) == false)
            {// 相対パス指定
                sRelativePath = sOriginalPath;
                bRtn = true;
            }
            else
            {// 絶対パス
                try
                {
                    ////ディレクトリパス指定チェック　指定されたパスがディレクトリと処理するためには、”\”が必要。
                    //if (sBasePath.Length > 0)
                    //{// ベースパス文字列有り
                    //    if (sBasePath.Substring(sBasePath.Length - 1).CompareTo("\\") != 0 && sBasePath.Substring(sBasePath.Length - 1).CompareTo("/") != 0)
                    //    {// "\"指定なしのため、付加する。
                    //        sBasePath = sBasePath + "\\";
                    //    }
                    //}
                    //else
                    //{// ベースパス指定無し
                    //    return false;
                    //}

                    //Uri uBasePath = new Uri(sBasePath);
                    //Uri uRelativePath = new Uri(sOriginalPath);
                    //sRelativePath = uBasePath.MakeRelativeUri(uRelativePath).ToString();
                    //sRelativePath = sRelativePath.Replace("/", "\\");

                    //if (sOriginalPath.CompareTo(sRelativePath) != 0)
                    //{// 変換成功
                    //    bRtn = true;
                    //}
                    //else
                    //{// ドライブ不一致
                    //    sRelativePath = "";
                    //}

                    sRelativePath = "";

                    if (sBasePath.Length <= 0)
                    {// ベースパス指定無し
                        return false;
                    }

                    string[] sBasePathDirs = sBasePath.Split('\\');
                    string[] sOriginalPathDirs = sOriginalPath.Split('\\');
                    int iBaseLength = sBasePathDirs.Length;
                    int iOriginalLength = sOriginalPathDirs.Length;

                    if (iBaseLength == 0 || iOriginalLength == 0)
                    {// 処理情報不足
                        return false;
                    }

                    if (sBasePathDirs[0].Equals(sOriginalPathDirs[0],StringComparison.OrdinalIgnoreCase) == true)
                    {// ドライブ一致
                        int iCnt = 0;

                        int ilength = (iBaseLength < iOriginalLength) ? iBaseLength : iOriginalLength;
                        for (int iLp = 0; iLp < ilength; iLp++)
                        {
                            if (sBasePathDirs[iLp].Equals(sOriginalPathDirs[iLp], StringComparison.OrdinalIgnoreCase) == true)
                            {// ディレクトリ一致
                                iCnt++;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // 相対位置を設定する
                        int iDirCount = iBaseLength - iCnt;
                        for (int iLp2 = 0; iLp2 < iDirCount; iLp2++)
                        {
                            sRelativePath = sRelativePath + "..\\";
                        }

                        // オリジナルパスを設定する
                        for (int iLp3 = iCnt; iLp3 < iOriginalLength; iLp3++)
                        {
                            if (iLp3 != iCnt)
                            {
                                sRelativePath = sRelativePath + "\\";
                            }
                            sRelativePath = sRelativePath + sOriginalPathDirs[iLp3];
                        }

                        bRtn = true;
                    }

                }
                catch
                {// 無効パス指定
                    sRelativePath = "";
                }
            }

            return bRtn;
        }

    }
}
