// <summary>ソースコード：ライブラリ出力CUI　ライブラリエクスポータークラス</summary>
// <author>CommonMP</author>
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

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

namespace CommonMP.HYMCO.CUI.HymcoCUI
{
    /// <summary><para>class outline:</para>
    /// <para>ライブラリ出力CUI　ライブラリエクスポータークラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>無し</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/12/14][新規作成]</para>
    /// </remarks>
    public class McLibraryExporter
    {
        /// <summary><para>method outline:</para>
        /// <para>出力実行</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> int  result = Export(exportInfo) </para>
        /// </example>
        /// <param name="exportInfo">ライブラリ出力情報</param>
        /// <returns><para>0: 正常終了 -1:ZIP形式変換エラー -2:入出力エラー</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public int Export(
            McLibraryExportInfo exportInfo
            )
        {
            HySString archiveFillFullPath = null;
            try
            {
                // アーカイブ対象エントリ作成
                List<KeyValuePair<HySStringRoot, HySStringRoot>> entryList = CreateTargetEntry(exportInfo);

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

                // アーカイブ出力実行
                archiveFillFullPath = exportInfo.GetArchiveFileFullpath();
                zipArchiver.Archive(archiveFillFullPath);
            }
            // Zipファイル形式エラー
            catch (Ionic.Zip.ZipException exp)
            {
                DeleteFile(archiveFillFullPath);
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(
                    HySLog.ONLINE,
                    "McLibraryExporter",
                    "Export",
                    Properties.HymcoCUIResources.STATEMENT_ARCHIVEOUT_EXCEPTION + exp.ToString() +
                    "archiveFillFullPath:" + archiveFillFullPath.ToString()
                    );
               // HySLog.LogOut(
               //     HySLog.ONLINE,
               //     "McLibraryExporter",
               //     "Export",
               //     "アーカイブ出力処理で例外発生:" + exp.ToString() +
               //     "archiveFillFullPath:" + archiveFillFullPath.ToString()
               //     );
                return -1;
            }
            catch (System.IO.FileNotFoundException exp)
            {
                DeleteFile(archiveFillFullPath);
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, "McLibraryExporter", "Export",
                    Properties.HymcoCUIResources.STATEMENT_ARCHIVEOUT_EXCEPTION + exp.ToString() + " " +
                    "archiveFillFullPath:" + archiveFillFullPath.ToString()
                    );
               // HySLog.LogOut(HySLog.ONLINE, "McLibraryExporter", "Export",
               //     "アーカイブ出力処理で例外発生:" + exp.ToString() + " " +
               //     "archiveFillFullPath:" + archiveFillFullPath.ToString()
               //    );
                return -2;
            }
            return 0;

            # region J# 固有処理
            //HySString archiveFillFullPath = null;
            //try
            //{
            //    // アーカイブ対象エントリ作成
            //    List<KeyValuePair<HySStringRoot, HySStringRoot>> entryList = CreateTargetEntry(exportInfo);

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

            //    // アーカイブ出力実行
            //    archiveFillFullPath = exportInfo.GetArchiveFileFullpath();
            //    zipArchiver.Archive(archiveFillFullPath);
            //}
            //// Zipファイル形式エラー
            //catch (java.util.zip.ZipException exp)
            //{
            //    DeleteFile(archiveFillFullPath);
            //    HySLog.LogOut(
            //        HySLog.ONLINE,
            //        "McLibraryExporter",
            //        "Export",
            //        "アーカイブ出力処理で例外発生:" + exp.ToString() +
            //        "archiveFillFullPath:" + archiveFillFullPath.ToString()
            //        );
            //    return -1;
            //}
            //// 入出力エラー
            //catch (java.io.IOException exp)
            //{
            //    DeleteFile(archiveFillFullPath);
            //    HySLog.LogOut(
            //        HySLog.ONLINE,
            //        "McLibraryExporter",
            //        "Export",
            //        "アーカイブ出力処理で例外発生:" + exp.ToString() + " " +
            //        "archiveFillFullPath:" + archiveFillFullPath.ToString()
            //        );
            //    return -1;
            //}
            //catch (System.IO.FileNotFoundException exp)
            //{
            //    DeleteFile(archiveFillFullPath);
            //    HySLog.LogOut(HySLog.ONLINE, "McLibraryExporter", "Export",
            //        "アーカイブ出力処理で例外発生:" + exp.ToString() + " " +
            //        "archiveFillFullPath:" + archiveFillFullPath.ToString()
            //        );
            //    return -2;
            //}
            //return 0;
            # endregion
        }

        /// <summary><para>method outline:</para>
        /// <para>エラーメッセージ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString message = GetErrorMessage(errorCode) </para>
        /// </example>
        /// <param name="errorCode">エラーコード</param>
        /// <returns><para>エラーメッセージ</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public HySString GetErrorMessage(
            int errorCode
            )
        {
            string errorComment = "";
            switch (errorCode)
            {
                case (-1):
                    errorComment = "ファイルにアクセスしようとして異常が発生しました。";
                    break;
                case (-2):
                    errorComment = "ディスク上に存在しないファイルにアクセスしようとして失敗しました。";
                    break;
                default:
                    break;
            }
            HySString message = new HySString(errorComment);
            return message;
        }

        /// <summary><para>method outline:</para>
        /// <para>ライブラリ出力対象ファイルエントリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List entries = CreateTargetEntry(exportInfo) </para>
        /// </example>
        /// <param name="exportInfo">ライブラリ出力情報</param>
        /// <returns><para>エントリ情報リスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static private List<KeyValuePair<HySStringRoot, HySStringRoot>> CreateTargetEntry(
            McLibraryExportInfo exportInfo
            )
        {
            List<KeyValuePair<HySStringRoot, HySStringRoot>> entries = new List<KeyValuePair<HySStringRoot, HySStringRoot>>();

            // プロジェクトフォルダパス取得
            HySString projectFolderFullpath = exportInfo.GetProjectFolderFullpath();
            HySString propertyPrjFolderFullPath = exportInfo.GetPropertyProjectFolderFullPath();

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

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

            //-----------------------------------------
            // 実行形式ファイル(.dll)のエントリ設定
            //-----------------------------------------
            // モデルプロジェクトの実行形式ファイル設定
            HySDataLinkedList binaryFullpathList = exportInfo.GetBinaryFullpathList();
            HySString entryRootFolPath = projectFolderFullpath + new HySString("\\bin\\Release");
          //HySString entryRootFolPath = projectFolderFullpath + "\\bin" + sPlatform + "\\Release"; // Ver1.5 追加（プラットフォーム取得）

            List<KeyValuePair<HySStringRoot, HySStringRoot>> binaryEntries =
                CreateTargetEntrySub(entryRootFolPath, binaryFullpathList, new HySString("bin"));
            entries.AddRange(binaryEntries);
            
            // プロパティ画面プロジェクトの実行形式ファイル設定
            HySString propertyPrjFolderPath = exportInfo.GetPropertyProjectFolderFullPath();
            
            if ((object)propertyPrjFolderPath != null)
            {
              //entryRootFolPath = propertyPrjFolderPath + new HySString("\\bin\\Release");
                entryRootFolPath = propertyPrjFolderPath + "\\bin" + sPlatform + "\\Release";

                // プロジェクト画面出力要
                HySDataLinkedList propertyPrjBinaryFullpathList = exportInfo.GetPropertyProjectBinaryFullpathList();
                List<KeyValuePair<HySStringRoot, HySStringRoot>> propertyPrjBinaryEntries =
                    CreateTargetEntrySub(entryRootFolPath, propertyPrjBinaryFullpathList, new HySString("bin"));
                entries.AddRange(propertyPrjBinaryEntries);
            }

            //-----------------------------------------
            // モデルアイコン(.ico)のエントリ設定
            //-----------------------------------------
            // ModelIconファイルのエントリ名とファイルフルパスをリストにセット
            HySDataLinkedList modelIconFullpathList = exportInfo.GetModelIconFullpathList();

            List<KeyValuePair<HySStringRoot, HySStringRoot>> entryList = CreateTargetEntrySub(
                projectFolderFullpath,
                modelIconFullpathList
                );
            entries.AddRange(entryList);

            //-----------------------------------------
            // モデル解説書(.pdf)のエントリ設定
            //-----------------------------------------
            // ModelManualファイルのエントリ名とファイルフルパスをリストにセット
            HySDataLinkedList manualFullpathList = exportInfo.GetManualFullPathList();

            entryList = CreateTargetEntrySub(
                projectFolderFullpath,
                manualFullpathList
                );
            entries.AddRange(entryList);

            //-----------------------------------------
            // 開発コードのエントリ設定
            //-----------------------------------------
            // 開発コード出力要否を判定する
            if (exportInfo.GetOutputSourceCode())
            {
                // モデルプロジェクトの開発コード設定
                HySDataLinkedList devSrcFullPathList = exportInfo.GetDevelopmentSourceFullPathList();
                List<KeyValuePair<HySStringRoot, HySStringRoot>> OutPutSrcEntries =
                CreateTargetEntrySub(projectFolderFullpath, devSrcFullPathList, new HySString("VsModelProject"));
                entries.AddRange(OutPutSrcEntries);
                
                // プロパティ画面プロジェクトの開発コード設定
                if ((object)propertyPrjFolderPath != null)
                {   // プロジェクト画面出力要
                    HySDataLinkedList propertyPrjDevSrcFullPathList = exportInfo.GetPropertyProjectDevSourceFullPathList();
                    List<KeyValuePair<HySStringRoot, HySStringRoot>> PropertyOutPutSrcEntries =
                    CreateTargetEntrySub(propertyPrjFolderPath, propertyPrjDevSrcFullPathList, new HySString("VsPropertyProject"));
                    entries.AddRange(PropertyOutPutSrcEntries);
                }
            }
 
            return entries;
        }

        /// <summary><para>method outline:</para>
        /// <para>ライブラリ出力対象ファイルエントリ作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List entries = CreateTargetEntrySub(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>> CreateTargetEntrySub(
            HySString projectFolderFullpath,
            HySDataLinkedList fileList
            )
        {
            List<KeyValuePair<HySStringRoot, HySStringRoot>> entries = new List<KeyValuePair<HySStringRoot,HySStringRoot>>();

            HySString entryName = new HySString();
            HySString listData = new HySString();
            for (int i = 0; i < (int)fileList.GetCount(); i++)
            {
                listData =(HySString)fileList.GetData(i);
                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> List entries = CreateTargetEntrySub(entryRootFolderFullPath, fullPathList, entryTopFolderNam) </para>
        /// </example>
        /// <param name="entryRootFolderFullPath">エントリのルートフォルダとなるフォルダパス</param>
        /// <param name="fileFullPathList">エントリ対象ファイルパスのリスト</param>
        /// <param name="entryTopFolderName">エントリの上位フォルダ名("[root]\XXXX\"のXXXXの部分)</param>
        /// <returns><para>エントリ情報リスト</para></returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>本メソッドはエントリの上位フォルダの名称を指定する場合に使用する。
        /// エントリ対象ファイルパスがない場合は要素数0のリストを返却する</para>
        /// </remarks>
        static private List<KeyValuePair<HySStringRoot, HySStringRoot>> CreateTargetEntrySub(
            HySString entryRootFolderFullPath,
            HySDataLinkedList fileFullPathList,
            HySString entryTopFolderName
            )
        {
            // (エントリ名、絶対ファイルパス)のキーペアリストを生成
            List<KeyValuePair<HySStringRoot, HySStringRoot>> entries =
                new List<KeyValuePair<HySStringRoot, HySStringRoot>>();

            // エントリ対象ファイルパスリストの要素数分、キーペア(エントリ)を作成
            fileFullPathList.SetCursorFirst();
            for (long lLp = 0; lLp < fileFullPathList.GetCount(); lLp++)
            {
                HySString filePath = (HySString)fileFullPathList.GetCursorData();
                //---------------------------------------------------------------------
                // エントリ名作成
                //   ファイルパス(filePath)が"C:\Project\classA.cs"で
                //   エントリ上位フォルダ名(entryTopFolderName)に"VsModelProject"を
                //   エントリルートパス(entryRootFolderFullPath)に"C:\Project"を
                //   指定した場合、エントリ名"VsModelProject\classA.cs"を作成する
                //---------------------------------------------------------------------
                HySString entryName = filePath.Clone().Remove(0, entryRootFolderFullPath.GetLength() + 1);
                entryName = entryTopFolderName + new HySString("\\") + entryName;
                KeyValuePair<HySStringRoot, HySStringRoot> entry =
                    new KeyValuePair<HySStringRoot, HySStringRoot>(entryName, filePath);
                entries.Add(entry);
                fileFullPathList.MoveCursorNext();
            }
            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);
            }
        }
    }
}
