// <summary>ソースコード：ツールのパッケージ化　ツール出力情報設定クラス</summary>
// <author>CommonMP</author>

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

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

namespace CommonMP.HYSSOP.OptionImpl.HySToolExport
{
    /// <summary><para>class outline:</para>
    /// <para>ツールのパッケージ化　ツール出力情報設定クラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>無し</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.3.0][2012/12/10][新規作成]</para>
    /// </remarks>
    public class HySToolExportInfoConverter
    {
        /// <summary><para>method outline:</para>
        /// <para>ツール出力情報変換</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> int iCode = ConvertToToolExportInfo(csProjectFolderFullPath, csExportFullpath, bIsOutputSource, out csExportInfo) </para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダフルパス</param>
        /// <param name="csExportFullpath">アーカイブ出力先フルパス</param>
        /// <param name="bIsOutputSource">開発コード出力要否</param>
        /// <param name="csExportInfo">ツール出力情報</param>
        /// <returns><para>0:正常 -1:プロジェクトフォルダパス不正 -2:アーカイブファイルパス不正 </para>
        /// <para>-3:実行形式ファイル無し</para>
        /// <para> -999:その他エラー</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public int ConvertToToolExportInfo(
            HySString csProjectFolderFullPath,
            HySString csExportFullPath,
            bool bIsOutputSource,
            out HySToolExportInfo csExportInfo
            )
        {
            const string METHOD_NAME = "ConvertToToolExportInfo";

            // 出力のツール出力情報
            csExportInfo = null;

            //--------------------------------------
            // プロジェクトパスとアーカイブ出力先パスをチェック
            // 相対パス指定の場合は絶対パスに変換
            //--------------------------------------
            try
            {
                // ツールプロジェクトのフォルダチェック
                bool bResult = System.IO.Path.IsPathRooted(csProjectFolderFullPath.ToString());
                if (bResult == false)
                {
                    csProjectFolderFullPath = new HySString(System.IO.Path.GetFullPath(csProjectFolderFullPath.ToString()));
                }
            }
            catch (ArgumentException ex)
            {   // プロジェクトフォルダに無効なものが含まれている例外が発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-1);
            }
            catch (PathTooLongException ex)
            {   // プロジェクトフォルダ名が最大長を超える例外が発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-1);
            }
            catch (NotSupportedException ex)
            {   // 呼び出されたメソッドがサポートされていない例外が発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-1);
            }
            catch (SecurityException ex)
            {   // セキュリティエラーが発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-1);
            }
            catch (NullReferenceException ex)
            {   // フォルダチェックでnull参照が発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:null" +
                    Environment.NewLine + ex.ToString());
                return (-999);
            }
            catch (Exception ex)
            {   // フォルダチェックで他の例外が発生した場合
                LogOut(METHOD_NAME, "csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-999);
            }

            try
            {
                // アーカイブ出力先フォルダチェック
                bool bResult = System.IO.Path.IsPathRooted(csExportFullPath.ToString());
                if (bResult == false)
                {
                    System.Environment.CurrentDirectory = System.IO.Directory.GetCurrentDirectory();
                    csExportFullPath = new HySString(System.IO.Path.GetFullPath(csExportFullPath.ToString()));
                }
            }
            catch (ArgumentException ex)
            {   // プロジェクトフォルダに無効なものが含まれている例外が発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:" +
                    csExportFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-2);
            }
            catch (PathTooLongException ex)
            {   // プロジェクトフォルダ名が最大長を超える例外が発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:" +
                    csExportFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-2);
            }
            catch (NotSupportedException ex)
            {   // 呼び出されたメソッドがサポートされていない例外が発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:" +
                    csExportFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-2);
            }
            catch (SecurityException ex)
            {   // セキュリティエラーが発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:" +
                    csExportFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-2);
            }
            catch (NullReferenceException ex)
            {   // フォルダチェックでnull参照が発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:null" +
                    Environment.NewLine + ex.ToString());
                return (-999);
            }
            catch (Exception ex)
            {   // フォルダチェックで他の例外が発生した場合
                LogOut(METHOD_NAME, "csExportFullPath:" +
                    csExportFullPath.ToString() + Environment.NewLine + ex.ToString());
                return (-999);
            }

            //-------------------------------------
            // ファイル/フォルダパスの有無チェック
            //-------------------------------------
            // プロジェクトフォルダパスの有無をチェック
            bool bIsDirectory = HySFileUtility.ExistDirectory(csProjectFolderFullPath);
            if (bIsDirectory == false)
            {
                LogOut(METHOD_NAME, "プロジェクトフォルダが存在しません。 csProjectFolderFullPath:" +
                    csProjectFolderFullPath.ToString());
                return (-1);
            }

            // アーカイブ出力先パスのファイルが存在するかチェック
            bool bIsFile = HySFileUtility.ExistFile(csExportFullPath);
            if (bIsFile == true)
            {
                LogOut(METHOD_NAME, "アーカイブ出力先のファイルが既に存在します。 exportFolderFullPath:" +
                    csExportFullPath.ToString());
                return (-2);
            }

            // アーカイブ出力先パスの有無をチェック
            string sExportPath = csExportFullPath.ToString().Substring(0, csExportFullPath.ToString().LastIndexOf('\\'));
            bIsDirectory = HySFileUtility.ExistDirectory(new HySString(sExportPath));
            if (bIsDirectory == false)
            {
                LogOut(METHOD_NAME, "アーカイブ出力先が存在しません。 exportFolderFullPath:" +
                    csExportFullPath.ToString());
                return (-2);
            }

            // アーカイブ出力先パスが有効かチェック
            bIsDirectory = HySFileUtility.EnableFileFullPath(csExportFullPath);
            if (bIsDirectory == false)
            {
                LogOut(METHOD_NAME, "アーカイブ出力先が有効ではありません。 exportFolderFullPath:" +
                    csExportFullPath.ToString());
                return (-2);
            }

            //------------------------
            // ツール出力情報作成
            //------------------------
            // ツールプロジェクト実行形式ファイルパス取得
            HySDataLinkedList csDllFileFullPathList = GetBinFileFullpathList(csProjectFolderFullPath);
            if (csDllFileFullPathList.GetCount() == 0)
            {
                LogOut(METHOD_NAME, "ツールプロジェクト実行形式ファイル無し");
                return (-3);
            }

            // ツールアイコンファイルパス取得
            HySDataLinkedList csToolIconFullPathList = GetToolIconPathList(csProjectFolderFullPath);

            // ツール解説書ファイルパス取得
            HySDataLinkedList csManualPathList = GetManualPathList(csProjectFolderFullPath);
            
            // 開発コード取得
            HySDataLinkedList csDevSrcFullPathList = null;
            if (bIsOutputSource == true)
            {
                // ツールプロジェクト開発コード
                csDevSrcFullPathList = GetDevelopmentSourceFullPathList(csProjectFolderFullPath);
            }

            //------------------------------------
            // ツール出力情報オブジェクト生成
            //------------------------------------
            HySToolExportInfo csToolExportInfo = new HySToolExportInfo(
                csProjectFolderFullPath,
                csExportFullPath,
                csDllFileFullPathList,
                csToolIconFullPathList
                );

            //------------------------
            // ツール出力情報設定
            //------------------------
            // ツールプロジェクト開発コード出力要否
            csToolExportInfo.SetOutputSourceCode(bIsOutputSource);  
            // ツール解説書ファイルパス                  
            csToolExportInfo.SetManualFullpathList(csManualPathList);
            // ツールプロジェクト開発コードファイルパスリスト
            csToolExportInfo.SetDevelopmentSourceFullPathList(csDevSrcFullPathList);

            csExportInfo = csToolExportInfo;
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>実行形式パスリスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedList csFilePathList = GetBinFileFullpathList(csProjectFolderFullPath) </para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダ名称</param>
        /// <returns><para>実行形式ファイルパスリスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private HySDataLinkedList GetBinFileFullpathList(
            HySString csProjectFolderFullPath
            )
        {
            HySDataLinkedList csBinFileList = new HySDataLinkedList();

            // Ver1.5 追加（プラットフォーム取得）
            string sPlatform = "\\x86";

            if (System.Environment.Is64BitProcess == true)
            {
                sPlatform = "\\x64";
            }

            // 実行形式ファイルの格納フォルダ存在有無チェック
            HySString csDllFolderFullpath = (csProjectFolderFullPath + "\\bin\\Release\\");
          //HySString csDllFolderFullpath = (csProjectFolderFullPath + "\\bin" + sPlatform + "\\Release" + "\\");   // Ver1.5 追加（プラットフォーム取得）

            if (System.IO.Directory.Exists(csDllFolderFullpath.ToString()))
            {
                /*
                 * 以下のファイルを取得
                 * ・ファイル名にプロジェクト名を含むDLLファイル
                 * ・CommonMP標準EXE以外のEXEファイル
                 */

                // 定義ファイルからCommonMPの標準exeファイル名の一覧を取得する
                HySString csCMPStdExeIniFileName = HySEnvInf.GetHomeDirectory() + "\\conf\\CMPStdExe.ini";
                HySIniFile csIniFile = new HySIniFile(csCMPStdExeIniFileName);
                HySString csCMPStdExeListString = csIniFile.GetValue(new HySString("CMP_STD_EXE"));
                string[] sCmpStdExeList = csCMPStdExeListString.ToString().Trim().Split(',');
                // CommonMPの標準exeファイル名一覧
                List<string> csCmpStdExeFileList = new List<string>(sCmpStdExeList);

                // 実行形式ファイルの格納フォルダ以下のファイルを全て取得
                HySDataLinkedList csFilePathList = HySFileUtility.GetFiles(csDllFolderFullpath);
                // プロジェクト名取得
                string sProjectName = GetLowestFolder(csProjectFolderFullPath);

                bool bDllExist = false;
                HySDataLinkedList csExeFileList = new HySDataLinkedList();
                for (int i = 0; i < csFilePathList.GetCount(); i++)
                {
                    HySString csFileFullPath = (HySString)(csFilePathList.GetData(i));
                    HySString csFileName = HySFileUtility.GetFileName(csFileFullPath);
                    HySString csExtension = HySFileUtility.GetExtension(csFileFullPath);
                    if ((object)csFileName != null && csFileName.ToString().Contains(sProjectName) == true &&
                        csExtension.ToString().Equals(".dll", StringComparison.CurrentCultureIgnoreCase))
                    {
                        // プロジェクト名称を含むDLLファイルの場合
                        bDllExist = true;
                        csBinFileList.AddLast(csFileFullPath);
                    }
                    else if ((object)csFileName != null && csCmpStdExeFileList.Contains(csFileName.ToString()) == false &&
                        csExtension.ToString().Equals(".exe", StringComparison.CurrentCultureIgnoreCase))
                    {
                        // CommonMP本体に含まれていないEXEファイルの場合
                        csBinFileList.AddLast(csFileFullPath);
                    }
                }

                // ツール本体（DLLファイル）がない場合は0件として返す（→エラーメッセージ）
                if (bDllExist == false)
                {
                    csBinFileList = new HySDataLinkedList();
                }
            }
            return csBinFileList;
        }

        /// <summary><para>method outline:</para>
        /// <para>ツールアイコンファイルパスリスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedList csToolIconPathList = GetToolIconPathList(HySString csProjectFolderFullPath) </para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダ名称</param>
        /// <returns><para>ツールアイコンファイルパスリスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private HySDataLinkedList GetToolIconPathList(
            HySString csProjectFolderFullPath
            )
        {
            const string METHOD_NAME = "GetToolIconPathList";

            HySDataLinkedList csToolIconFilePathList = new HySDataLinkedList();
            HySString csToolIconFolderRelativePath = null;
            try
            {
                csToolIconFolderRelativePath = HySEnvInf.GetEnvInf("TOOL_ICON_FILE_PATH");
            }
            catch (Exception ex)
            {
                // 定義値取得に失敗した場合、デフォルト名をセット
                LogOut(METHOD_NAME, "設定情報:TOOL_ICON_FILE_PATH の取得に失敗" +
                    Environment.NewLine + ex.ToString());
                csToolIconFolderRelativePath = new HySString(@"\ToolIcon\");
            }

            if (System.IO.Directory.Exists((csProjectFolderFullPath + csToolIconFolderRelativePath).ToString()))
            {
                // ツールアイコンフォルダ以下のファイルパスのリストを取得（フルパス）
                HySDataLinkedList csPathList = HySFileUtility.GetFiles(csProjectFolderFullPath + csToolIconFolderRelativePath);

                for (int i = 0; i < csPathList.GetCount(); i++)
                {
                    HySString csExtension = HySFileUtility.GetExtension((HySString)csPathList.GetData(i));
                    if (((object)csExtension != null) && (
                        csExtension.ToString().Equals(".ico", StringComparison.CurrentCultureIgnoreCase)))
                    {
                        csToolIconFilePathList.AddLast(csPathList.GetData(i));
                    }
                }
            }
            return csToolIconFilePathList;
        }

        /// <summary><para>method outline:</para>
        /// <para>ツール解説書ファイルパスリスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedList csManualList = GetManualPathList(HySString csProjectFolderFullPath) </para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダ名称</param>
        /// <returns><para>ツール解説書ファイルパスリスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private HySDataLinkedList GetManualPathList(
            HySString csProjectFolderFullpath
            )
        {
            const string METHOD_NAME = "GetManualPathList";

            HySDataLinkedList csToolManualFilePathList = new HySDataLinkedList();
            HySString csManualFolderRelativePath = null;
            try
            {
                csManualFolderRelativePath = HySEnvInf.GetEnvInf("TOOL_MANUAL_FOLDER");
            }
            catch (Exception ex)
            {
                // 定義値取得に失敗した場合、デフォルト名をセット
                LogOut(METHOD_NAME, "設定情報:TOOL_MANUAL_PATH の取得に失敗" +
                    Environment.NewLine + ex.ToString());
                csManualFolderRelativePath = new HySString(@"\ToolManual");
            }

            if (System.IO.Directory.Exists((csProjectFolderFullpath + csManualFolderRelativePath).ToString()))
            {
                // ツール解説書フォルダ以下のファイルパスのリストを取得
                HySDataLinkedList csPathList = HySFileUtility.GetFiles(csProjectFolderFullpath + csManualFolderRelativePath);

                for (int i = 0; i < csPathList.GetCount(); i++)
                {
                    HySString csExtension = HySFileUtility.GetExtension((HySString)csPathList.GetData(i));
                    if (((object)csExtension != null) && (
                        csExtension.ToString().Equals(".pdf", StringComparison.CurrentCultureIgnoreCase)))
                    {
                        csToolManualFilePathList.AddLast(csPathList.GetData(i));
                    }
                }
            }
            return csToolManualFilePathList;
        }

        /// <summary><para>method outline:</para>
        /// <para>開発コードファイルパスリスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedList csDevSrcFullPathList = GetDevelopmentSourceFullPathList(HySString csProjectFolderFullPath) </para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダ名称</param>
        /// <returns><para>開発コードファイルパスリスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>プロジェクトフォルダ以下のファイルをリストで返却する。</para>
        /// <para>ただし、bin,objフォルダ以下のファイルは含まないものとする。(フォルダパスのみリストに追加する。)</para>
        /// </remarks>
        static private HySDataLinkedList GetDevelopmentSourceFullPathList(
            HySString csProjectFolderFullpath
            )
        {
            HySDataLinkedList csDevSrcFullPathList = new HySDataLinkedList();

            HySDataLinkedList csDevFiles = HySFileUtility.GetFiles(csProjectFolderFullpath);
            HySString csExtension = new HySString();
            bool bExistBin = false;
            bool bExistObj = false;
            bool bBinResult;
            bool bObjResult;

            // "bin","obj"フォルダ以外のファイルフルパスをリストに追加
            for (int i = 0; i < csDevFiles.GetCount(); i++)
            {
                // プロジェクトフォルダ以下のbin,objフォルダ以外のファイル名フルパスをリストに追加
                HySString csFileName = (HySString)csDevFiles.GetData(i);
                bBinResult = csFileName.ToString().StartsWith(csProjectFolderFullpath.ToString() + "\\bin\\");
                bObjResult = csFileName.ToString().StartsWith(csProjectFolderFullpath.ToString() + "\\obj\\");
                
                if (bBinResult == true)
                {
                    bExistBin = true;
                }
                else if (bObjResult == true)
                {
                    bExistObj = true;
                }
                else if (bBinResult == false && bObjResult == false)
                {
                    csDevSrcFullPathList.AddLast(csDevFiles.GetData(i));
                }
            }

            // "bin","obj"フォルダが1つでも存在する場合は空フォルダをリストに追加
            if (bExistBin == true)
            {
                HySString csBinFolderPath = new HySString(csProjectFolderFullpath.ToString() + @"\bin");
                csDevSrcFullPathList.AddLast(csBinFolderPath);
            }
            if (bExistObj == true)
            {
                HySString csObjFolderPath = new HySString(csProjectFolderFullpath.ToString() + @"\obj");
                csDevSrcFullPathList.AddLast(csObjFolderPath);
            }

            return csDevSrcFullPathList;
        }

        /// <summary><para>method outline:</para>
        /// <para>プロジェクト名称取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sProjectName = GetLowestFolder(HySString csProjectFolderFullPath)</para>
        /// </example>
        /// <param name="csProjectFolderFullPath">プロジェクトフォルダ名称</param>
        /// <returns><para>プロジェクト名称</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private string GetLowestFolder(HySString csProjectFolderFullPath)
        {
            string sFolderPath = csProjectFolderFullPath.ToString();
            string[] sSplitFolderPath = sFolderPath.Split('\\');

            string sProjectName = "";
            if (sSplitFolderPath[sSplitFolderPath.Length - 1] == "")
            {
                sProjectName = sSplitFolderPath[sSplitFolderPath.Length - 2];
            }
            else
            {
                sProjectName = sSplitFolderPath[sSplitFolderPath.Length - 1];
            }

            return sProjectName;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>ログ出力処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> LogOut(sMethodName, sMessage) </para>
        /// </example>
        /// <param name="sMethodName">メソッド名称</param>
        /// <param name="sMessage">出力メッセージ</param>
        /// <returns><para>無し</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void LogOut(string sMethodName, string sMessage)
        {
            HySToolExportProgram.ErrorLOG("HySToolExportInfoConverter." + sMethodName, sMessage);
        }
    }
}
