// <summary>ソースコード：ＨＹＭＣＯポータブルデータ作成画面クラス</summary>
// <author>CommonMP</author>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.Interface.HSTools;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYSSOP.OptionImpl.HSViewer.DotNetViewer;
using CommonMP.HYMCO.CoreImpl.Tool.Msg;

namespace CommonMP.HYMCO.CoreOptions.McViewer.DotNetViewer
{
    /// <summary><para>class outline:</para>
    /// <para>ポータブルデータ作成画面</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.1.0][2010/12/09][新規作成]</para>
    /// </remarks>
    public partial class McDotNetPortableDataMakeForm : HySDotNetForm
    {
        /// <summary>クラス名称</summary>
        static private readonly string CLASS_NAME = "McDotNetPortableDataMakeForm";

        /// <summary>ポータブルデータ作成画面タイトル</summary>
        static private readonly string PORTABLE_MAKE_DLG_TITLE = Properties.McDotNetViewerResources.ResourceManager.GetString("FILE_DLG_TITLE_MAKE_PORTABLE");
        /// <summary>ポータブルデータ作成画面フィルター</summary>
        static private readonly string PORTABLE_SAVE_DLG_FILTER = Properties.McDotNetViewerResources.ResourceManager.GetString("FILE_DLG_FILTER_ARCHIVE");

        /// <summary>メッセージタイトル </summary>
        static private readonly string MSGBOX_TITLE = McMessage.GetString("MC_MSG_TITLE_PROJECT_MANAGEMENT");
        /// <summary>メッセージ「正常終了」 </summary>
        static private string MSG_COMPLETE_MAKE_PORTABLE = McMessage.GetString("MC_MSG_INFO_COMPLETE_MAKE_PORTABLE");
        /// <summary>メッセージ「警告：容量オーバー」 </summary>
        static private readonly string MSG_WARNING_SIZEOVER_PORTABLE = McMessage.GetString("MC_MSG_WARNING_SIZEOVER_PORTABLE");
        /// <summary>メッセージ「警告：ファイル数オーバー」 </summary>
        static private readonly string MSG_WARNING_COUNTOVER_PORTABLE = McMessage.GetString("MC_MSG_WARNING_COUNTOVER_PORTABLE");
        /// <summary>メッセージ「異常終了」 </summary>
        static private readonly string MSG_ERR_MAKE_PORTABLE = McMessage.GetString("MC_MSG_ERROR_MAKE_PORTABLE");
        /// <summary>メッセージ「プロジェクトグループが指定されていません。」 </summary>
        static private string MSG_CHK_INMPUT_MAKE_PORTABLE = McMessage.GetString("MC_MSG_CHECK_INMPUT_MAKE_PORTABLE");

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McDotNetPortableDataMakeForm csPortableDataMakeForm = new McDotNetPortableDataMakeForm();</para>
        /// </example>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McDotNetPortableDataMakeForm()
        {
            InitializeComponent();
            LoadFolderList();
        }

        /// <summary><para>method outline</para>
        /// <para>対象フォルダ表示処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>LoadFolderList();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void LoadFolderList()
        {
            try
            {
                HySString csFilePath = HySEnvInf.GetDataHomeDirectory();    // データホームディレクトリ

                if ((object)csFilePath != null)
                {// 取得成功

                    DirectoryInfo selectedDir = new DirectoryInfo(csFilePath.ToString());   // データホームディレクトリ内サブディレクトリ

                    if (selectedDir.Exists) //ディレクトリが存在すればノードに追加
                    {
                        DirectoryInfo[] subDirInfo = selectedDir.GetDirectories();  // プロジェクトグループディレクトリ取得

                        foreach (DirectoryInfo di in subDirInfo)
                        {// プロジェクトグループディレクトリを格納
                            ProjectGroup_List.Items.Add(di.Name);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, CLASS_NAME, "LoadFolderList", 
                    Properties.McDotNetViewerResources.STATEMENT_DIR_DSP_EXCEP  + Environment.NewLine + ex.ToString());
               // HySLog.LogOut(HySLog.ONLINE, CLASS_NAME, "LoadFolderList", "対象フォルダ表示処理で例外発生:" + Environment.NewLine + ex.ToString());
            }

        }

        /// <summary><para>method outline</para>
        /// <para>「作成」ボタンクリック時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>this.Make_Button.Click += new System.EventHandler(this.ExportData);</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 ExportData(object sender, EventArgs e)
        {
            long lRtn = 0;
            // デフォルトファイル名
            string projectName = "ProjectData";

            if (ProjectGroup_List.CheckedItems.Count == 0)
            {
                MessageBox.Show(MSG_CHK_INMPUT_MAKE_PORTABLE, MSGBOX_TITLE);
                return;
            }

            // ポータブルデータ保存画面設定
            SaveFileDialog saveFileDlg = new SaveFileDialog();
            saveFileDlg.FileName = projectName + ".zip";
            saveFileDlg.InitialDirectory = HySEnvInf.GetDataHomeDirectory().ToString();
            saveFileDlg.Title = PORTABLE_MAKE_DLG_TITLE;
            saveFileDlg.Filter = PORTABLE_SAVE_DLG_FILTER;
            saveFileDlg.RestoreDirectory = true; 

            // ポータブルデータ保存画面表示
            if (saveFileDlg.ShowDialog() == DialogResult.OK)
            {
                HySString csFileFullPath = new HySString(saveFileDlg.FileName);
                // ポータブルデータ作成実行
                this.Cursor = Cursors.WaitCursor;
                lRtn = MakePortableData(csFileFullPath);
                this.Cursor = Cursors.Default;

                // 終了メッセージ
                if (lRtn == 0)
                {// 正常終了
                    MessageBox.Show(MSG_COMPLETE_MAKE_PORTABLE, MSGBOX_TITLE);
                }
                else if (lRtn == -3)
                {// エントリー数オーバー
                    MessageBox.Show(MSG_WARNING_COUNTOVER_PORTABLE, MSGBOX_TITLE);
                }
                else if (lRtn == -4)
                {// サイズオーバー
                    MessageBox.Show(MSG_WARNING_SIZEOVER_PORTABLE, MSGBOX_TITLE);
                }
                else
                {// 異常終了
                    MessageBox.Show(MSG_ERR_MAKE_PORTABLE, MSGBOX_TITLE);
                }

                this.Close();
            }

        }

        /// <summary><para>method outline</para>
        /// <para>「キャンセル」ボタンクリック時処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>this.Cancel_Button.Click += new System.EventHandler(this.Cancel);</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(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary><para>method outline</para>
        /// <para>ポータブルデータ作成処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = MakePortableData(csFileFullPath)</para>
        /// </example>
        /// <param name="csFileFullPath">ポータブルデータファイル出力先パス</param>
        /// <returns>0: 正常終了 -1:ZIP形式変換エラー -2:入出力エラー</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private long MakePortableData(HySString csFileFullPath)
        {
            try
            {
                HySDataLinkedList csFileList = this.GetFileList();
                long lEntCnt = csFileList.GetCount();
                if (lEntCnt >= 65535)
                {// エントリー数オーバー
                   // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(
                        HySLog.ONLINE,
                        CLASS_NAME,
                        "MakePortableData",
                        Properties.McDotNetViewerResources.STATEMENT_PORTAL_FILE_OVER + lEntCnt.ToString() +
                        "csFileFullPath:" + csFileFullPath.ToString()
                        );
                   // HySLog.LogOut(
                   //     HySLog.ONLINE,
                   //     CLASS_NAME,
                   //     "MakePortableData",
                   //     "ポータブルデータ作成指定ファイル数オーバー:" + lEntCnt.ToString() +
                   //     "csFileFullPath:" + csFileFullPath.ToString()
                   //     );
                    return -3;
                }
                // ポータブルデータ対象エントリ作成
                List<KeyValuePair<HySStringRoot, HySStringRoot>> entryList = CreateTargetEntry(HySEnvInf.GetDataHomeDirectory(), csFileList);

                // エントリを追加
                HySArchiver zipArchiver = new HySDotNetZipArchiver();
                zipArchiver.AddEntry(entryList);

                // ポータブルデータ作成実行
                zipArchiver.Archive(csFileFullPath);

                FileInfo csFileInfo = new FileInfo(csFileFullPath.ToString());
                long lSize = csFileInfo.Length;
                if (lSize >= 2147483647)
                {// サイズオーバー
                   // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(
                        HySLog.ONLINE,
                        CLASS_NAME,
                        "MakePortableData",
                        Properties.McDotNetViewerResources.STATEMENT_PORTAL_SIZE_OVER + lSize.ToString() +
                        "csFileFullPath:" + csFileFullPath.ToString()
                        );
                   // HySLog.LogOut(
                   //     HySLog.ONLINE,
                   //     CLASS_NAME,
                   //     "MakePortableData",
                   //     "ポータブルデータ作成サイズオーバー:" + lSize.ToString() +
                   //     "csFileFullPath:" + csFileFullPath.ToString()
                   //     );
                    return -4;
                }
            }
            // Zipファイル形式エラー
            catch (Ionic.Zip.ZipException exp)
            {
                DeleteFile(csFileFullPath);
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(
                    HySLog.ONLINE,
                    CLASS_NAME,
                    "MakePortableData",
                    Properties.McDotNetViewerResources.STATEMENT_PORTAL_EXCEP + exp.ToString() +
                    "csFileFullPath:" + csFileFullPath.ToString()
                    );
               // HySLog.LogOut(
               //     HySLog.ONLINE,
               //     CLASS_NAME,
               //     "MakePortableData",
               //     "ポータブルデータ作成処理で例外発生:" + exp.ToString() +
               //     "csFileFullPath:" + csFileFullPath.ToString()
               //     );
                return -1;
            }
            catch (System.IO.FileNotFoundException exp)
            {
                DeleteFile(csFileFullPath);
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, CLASS_NAME, "MakePortableData",
                    Properties.McDotNetViewerResources.STATEMENT_PORTAL_EXCEP + exp.ToString() + " " +
                    "csFileFullPath:" + csFileFullPath.ToString()
                    );
               // HySLog.LogOut(HySLog.ONLINE, CLASS_NAME, "MakePortableData",
               //     "ポータブルデータ作成処理で例外発生:" + exp.ToString() + " " +
               //     "csFileFullPath:" + csFileFullPath.ToString()
               //     );
                return -2;
            }
            return 0;
        }

        /// <summary><para>method outline</para>
        /// <para>圧縮対象ファイルリスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySDataLinkedList csDataLinkedList = GetFileList()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>圧縮対象ファイルリスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySDataLinkedList GetFileList()
        {
            HySDataLinkedList csFileList = new HySDataLinkedList();
            string csProjectGroupName;      // プロジェクトグループ名
            string[] sDirectorys;           // 対象ディレクトリ
            string[] sFiles;                // 対象ファイル

            for (int iLp = 0; iLp < ProjectGroup_List.Items.Count; iLp++)
            {
                //選択プロジェクト
                if (ProjectGroup_List.GetItemChecked(iLp) == true)
                {
                    csProjectGroupName = HySEnvInf.GetDataHomeDirectory().ToString() + "\\" + ProjectGroup_List.Items[iLp].ToString();
                    sDirectorys = Directory.GetDirectories(csProjectGroupName, "*", SearchOption.AllDirectories);
                    sFiles = Directory.GetFiles(csProjectGroupName, "*", SearchOption.AllDirectories);

                    //対象ディレクトリを取得
                    foreach (string sDirItem in sDirectorys)
                    {
                        csFileList.AddLast(new HySString(sDirItem));
                    }
                    //対象ファイルを取得
                    foreach (string sFileItem in sFiles)
                    {
                        csFileList.AddLast(new HySString(sFileItem));
                    }
                }
            }

            return csFileList;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力対象ファイルエントリ作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List entries = CreateTargetEntry(projectFolderFullpath,fileList) </para>
        /// </example>
        /// <param name="projectFolderFullpath">プロジェクトフォルダフルパス</param>
        /// <param name="fileList">ファイルリスト</param>
        /// <returns><para>エントリ情報リスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private List<KeyValuePair<HySStringRoot, HySStringRoot>> CreateTargetEntry(
            HySString projectFolderFullpath,
            HySDataLinkedList fileList
            )
        {
            List<KeyValuePair<HySStringRoot, HySStringRoot>> entries = new List<KeyValuePair<HySStringRoot, HySStringRoot>>();

            HySString entryName = new HySString();
            HySString listData = new HySString();
            for (int iLp = 0; iLp < (int)fileList.GetCount(); iLp++)
            {
                listData = (HySString)fileList.GetData(iLp);
                entryName = new HySString(
                    listData.ToString().Remove(0, (projectFolderFullpath.ToString().Length) + 1)
                    );
                KeyValuePair<HySStringRoot, HySStringRoot> pair = new KeyValuePair<HySStringRoot, HySStringRoot>(
                    entryName,
                    listData
                    );
                entries.Add(pair);
            }
            return entries;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>ファイル削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> DeleteFile(fileFullPath) </para>
        /// </example>
        /// <param name="fileFullPath">ファイルフルパス</param>
        /// <returns><para>無し</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private void DeleteFile(HySString fileFullPath)
        {
            bool result = HySFileUtility.ExistFile(fileFullPath);
            if (result == true)
            {
                HySFileUtility.Delete(fileFullPath);
            }
        }

        /// <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_PROJECT_0009, null);
        }

    }
}
