// <summary>ソースコード：ツールのパッケージ化画面クラス</summary>
// <author>CommonMP</author>

using System;
using System.Windows.Forms;
using System.IO;

using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYMCO.CoreImpl.Tool.Msg;


namespace CommonMP.HYSSOP.OptionImpl.HySToolExport
{
    /// <summary><para>class outline:</para>
    /// <para>パッケージ出力画面</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.3.0][2012/12/10][新規作成]</para>
    /// </remarks>
    public partial class HySToolExportForm : Form
    {
        /// <summary>環境情報管理クラス</summary>
        private HySEnvInf m_csEnvInf;

        /// <summary>クラス名文字列</summary>
        static private readonly string CLASS_NAME = "HySToolExportForm";

        /// <summary>アーカイブ保存画面タイトル</summary>
        static private readonly string TOOL_SAVE_DLG_TITLE = Properties.HySToolExportResources.ResourceManager.GetString("FILE_DLG_TITLE_SAVE_ARCHIVE");
        /// <summary>ツールパッケージ拡張子</summary>
        static private readonly string TOOL_PACKAGE_EXTENSION = ".toollib";
        /// <summary>アーカイブ保存時拡張子フィルター</summary>
        static private readonly string TOOL_SAVE_DLG_FILTER = Properties.HySToolExportResources.ResourceManager.GetString("FILE_DLG_FILTER_ARCHIVE");
        /// <summary>フォルダ参照画面解説</summary>
        static private readonly string FOLDER_REF_DLG_DESCRIPTION = Properties.HySToolExportResources.ResourceManager.GetString("FILE_DLG_SELECT_PROJFLD");

        /// <summary>通常メッセージタイトル </summary>
        static private readonly string MSGBOX_TITLE = McMessage.GetString("MC_MSG_TITLE_LIBRARY_REGISUT_SUPPORT");
        /// <summary>メッセージ「正常終了」 </summary>
        static private string MSG_COMPLETE_TOOL_EXPORT = McMessage.GetString("MC_MSG_INFO_COMPLETE_PACKAGE");
        /// <summary>メッセージ「異常終了」 </summary>
        static private readonly string MSG_ERR_TOOL_EXPORT = McMessage.GetString("MC_MSG_ERROR_PACKAGE");

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySToolExportForm csForm = new HySToolExportForm();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySToolExportForm 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySToolExportForm()
        {
            InitializeComponent();
            // 環境情報ファイルの初期化を行う
            m_csEnvInf = new HySEnvInf(new HySString("CommonMP.cfg"));
            m_csEnvInf.InitializeNoLog();
            // ログファイル設定
            HySToolExportProgram.StartLOG();

            Archive_Button.Enabled = false;
        }
        
        /// <summary><para>method outline</para>
        /// <para>「フォルダ参照」釦クリック時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>this.FolderRef_Button.Click += new System.EventHandler(this.FolderRef_Button_Click);</para>
        /// </example>
        /// <param name="sender">object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void FolderRef_Button_Click(object sender, EventArgs e)
        {
            // フォルダ参照画面作成
            FolderBrowserDialog csFolderBrowserDlg = CreateFolderBlowseDialog();

            // フォルダ参照画面表示
            if (csFolderBrowserDlg.ShowDialog(this) == DialogResult.OK)
            {
                ProjectFolderFullPath_TextBox.Text = csFolderBrowserDlg.SelectedPath;
                // アーカイブ釦の状態変更
                UpdateArchiveButtonState();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>「アーカイブ」釦クリック時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Archive_Button.Click += new System.EventHandler(this.Archive_Button_Click);</para>
        /// </example>
        /// <param name="sender">object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks> 
        private void Archive_Button_Click(object sender, EventArgs e)
        {
            // プロジェクト名称取得
            string sProjectName = GetProjectName();

            // アーカイブ保存画面設定
            SaveFileDialog csSaveFileDlg = new SaveFileDialog();
            csSaveFileDlg.FileName = sProjectName + TOOL_PACKAGE_EXTENSION;
            csSaveFileDlg.InitialDirectory = CreateSelectFolderFullPath();
            csSaveFileDlg.Title = TOOL_SAVE_DLG_TITLE;
            csSaveFileDlg.Filter = TOOL_SAVE_DLG_FILTER;
            csSaveFileDlg.RestoreDirectory = true;
            csSaveFileDlg.OverwritePrompt = false;

            // アーカイブ保存画面表示
            if (csSaveFileDlg.ShowDialog() == DialogResult.OK)
            {
                // アーカイブ出力実行
                Archive(csSaveFileDlg.FileName);
            }
        }
        
        /// <summary><para>method outline</para>
        /// <para>「キャンセル」釦クリック時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>this.Cancel_Button.Click += new System.EventHandler(this.Cancel_Button_Click);</para>
        /// </example>
        /// <param name="sender">object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void Cancel_Button_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary><para>method outline</para>
        /// <para>アーカイブ出力処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Archive(sArchiveFileFullPath)</para>
        /// </example>
        /// <param name="sArchiveFileFullPath">アーカイブファイル出力先パス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void Archive(string sArchiveFileFullPath)
        {
            const string sMethodName = "Archive";
            int iStatus = 0;

            try
            {
                int iReturnVal = ExportTool(sArchiveFileFullPath);
                if (iReturnVal == 0)
                {   // 正常終了
                    MessageBox.Show(
                        MSG_COMPLETE_TOOL_EXPORT,
                        MSGBOX_TITLE,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information
                        );
                }
                else
                {   // 異常終了
                    MessageBox.Show(
                        GetErrorMessage(iReturnVal),
                        MSGBOX_TITLE,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error
                        );
                    HySToolExportProgram.ErrorLOG(CLASS_NAME + "." + sMethodName,
                        GetErrorMessage(iReturnVal));
                    iStatus = -1;
                }
            }
            catch (System.Exception ex)
            {
                ExceptionalCase(sMethodName,
                    "パッケージ出力に失敗しました: " + sArchiveFileFullPath +
                    Environment.NewLine + ex.ToString());
                iStatus = -1;
            }
            finally
            {
                if (iStatus == 0)
                {
                    // 正常終了時は画面を閉じる
                    this.Close();
                }
            }
        }

        /// <summary><para>method outline</para>
        /// <para>プロジェクト名称取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sProjectName = GetProjectName()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>プロジェクト名称</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private string GetProjectName()
        {
            string sProjectName = "";
            string sPrjFolderFullPath = ProjectFolderFullPath_TextBox.Text;
            if (sPrjFolderFullPath.EndsWith(":\\"))
            {   // ドライブ名を指定された場合は空文字を返却する
                return sProjectName;
            }

            // プロジェクト名を取り出す
            // 「\xxx\yyy\」のようにパスの最後が"\"で指定された場合を考慮し、
            // splitPathの最後の要素が空白の場合は最後から2番目の要素を返却する
            string[] sSplitPath = sPrjFolderFullPath.Split('\\');
            if (sSplitPath[sSplitPath.Length - 1] == "")
            {   // 最後の要素が空白の場合
                sProjectName = sSplitPath[sSplitPath.Length - 2];
            }
            else
            {
                sProjectName = sSplitPath[sSplitPath.Length - 1];
            }

            return sProjectName;
        }

        /// <summary><para>method outline</para>
        /// <para>選択フォルダパス作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sSelectFolderPath = CreateSelectFolderFullPath()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>選択フォルダパス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private string CreateSelectFolderFullPath()
        {
            HySString csHomeDir = HySEnvInf.GetHomeDirectory();
            DirectoryInfo csDirInfo = Directory.GetParent(csHomeDir.ToString());
            return csDirInfo.ToString();
        }

        /// <summary><para>method outline</para>
        /// <para>例外発生時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ExceptionalCase(sMethodName, sMessage)</para>
        /// </example>
        /// <param name="sMethodName">メソッド名</param>
        /// <param name="sMessage">出力メッセージ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void ExceptionalCase(string sMethodName, string sMessage)
        {
            // エラー内容をログ出力
            HySToolExportProgram.ErrorLOG(CLASS_NAME + "." + sMethodName, sMessage);

            // エラーメッセージ表示
            MessageBox.Show(
                MSG_ERR_TOOL_EXPORT,
                MSGBOX_TITLE,
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
                );
        }

        /// <summary><para>method outline</para>
        /// <para>ヘルプリンクイベント</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HelpJump_Button_Click(sender, e)</para>
        /// </example>
        /// <param name="sender">object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void HelpJump_Button_Click(object sender, EventArgs e)
        {
            // ヘルプ画面の表示
            HySShowHelpNavigator.ShowHelpNavigator(HySShowHelpNavigator.NAV_MSG_TOOL_0005, null);
        }

        /// <summary><para>method outline</para>
        /// <para>フォルダ参照画面作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>FolderBrowserDialog csFolderBrowserDlg = CreateFolderBlowseDialog()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>フォルダ参照画面</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private FolderBrowserDialog CreateFolderBlowseDialog()
        {
            // フォルダ参照画面生成
            FolderBrowserDialog csFolderBrowserDlg = new FolderBrowserDialog();
            // 画面設定
            csFolderBrowserDlg.Description = FOLDER_REF_DLG_DESCRIPTION;
            csFolderBrowserDlg.SelectedPath = CreateSelectFolderFullPath();
            csFolderBrowserDlg.ShowNewFolderButton = false;

            return csFolderBrowserDlg;
        }

        /// <summary><para>method outline</para>
        /// <para>「アーカイブ」釦状態更新</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>UpdateArchiveButtonState()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>画面の状態からボタンコントロールのマスク制御を行う</para>
        /// </remarks>
        protected void UpdateArchiveButtonState()
        {
            Archive_Button.Enabled = false;
            // プロジェクトフォルダパスが入力済みか判定
            if (ProjectFolderFullPath_TextBox.Text != string.Empty)
            {   // 空白じゃなければ活性
                Archive_Button.Enabled = true;
            }
        }
        
        /// <summary><para>method outline</para>
        /// <para>実行結果メッセージ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sMessage = GetResultErrorMessage(iResult)</para>
        /// </example>
        /// <param name="iResult">リターンコード</param>
        /// <returns>実行結果メッセージ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private string GetErrorMessage(int iResult)
        {
            string sMessage = MSG_ERR_TOOL_EXPORT;
            switch (iResult)
            {
                case (-1):
                    // プロジェクトフォルダパス不正
                    sMessage = McMessage.GetString("MC_MSG_ERROR_PROJECT_FOLDER_PATH");
                    break;
                case (-2):
                    // アーカイブファイルパス不正
                    // 内部的には様々なケースが存在するが、実操作上はファイル重複でしか発生しない
                    sMessage = McMessage.GetString("MC_MSG_ERROR_ARCHIVE_FILE_PATH");
                    break;
                case (-3):
                    // ツールの本体（DLLファイル）無し
                    sMessage = McMessage.GetString("MC_MSG_ERROR_NOT_DLL_FILE");
                    break;
                case (-4):
                    // ファイル入力異常
                    sMessage = McMessage.GetString("MC_MSG_ERROR_FILE_INPUT");
                    break;
                case (-5):
                    // ファイルアクセス異常
                    sMessage = McMessage.GetString("MC_MSG_ERROR_FILE_ACCESS");
                    break;
                case (-999):
                    // 想定外のエラー
                    sMessage = "パッケージ出力に失敗しました。";
                    break;
                default:
                    break;
            }
            return sMessage;
        }

        /// <summary><para>method outline:</para>
        /// <para>パッケージ出力処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>int iErrorCode = ExportTool(sArchiveFileFullPath) </para>
        /// </example>
        /// <param name="sArchiveFileFullPath">アーカイブ出力ファイルフルパス</param>
        /// <returns><para>リターンコード</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private int ExportTool(string sArchiveFileFullPath)
        {
            try
            {
                // 出力情報の設定を行う
                HySToolExportInfo csExportInfo;
                int result = HySToolExportInfoConverter.ConvertToToolExportInfo(
                    new HySString(ProjectFolderFullPath_TextBox.Text),
                    new HySString(sArchiveFileFullPath),
                    IncludeDevSource_CheckBox.Checked,
                    out csExportInfo);
                if (result != 0)
                {
                    // エラーメッセージは呼び出し元で表示する
                    return result;
                }

                // 出力実行を行う
                result = HySToolExporter.Export(csExportInfo);
                if (result != 0)
                {
                    // エラーメッセージは呼び出し元で表示する
                    return result;
                }
            }
            catch (Exception ex)
            {   // 想定外のエラー
                ExceptionalCase("ExportTool",
                    "パッケージ出力に失敗しました: " + sArchiveFileFullPath +
                    Environment.NewLine + ex.ToString());
                return (-999);
            }

            return 0;
        }
    }
}