// <summary>ソースコード：アーカイバクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Ionic.Zip;

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

namespace CommonMP.HYSSOP.CoreImpl.HSTools
{
    /// <summary><para>class outline:</para>
    /// <para>アーカイバクラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>無し</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/12/03][新規作成]</para>
    /// </remarks>
    public class HySDotNetZipArchiver : HySArchiver
    {
        /// <summary> エントリ情報リスト </summary>
        private List<KeyValuePair<HySStringRoot, HySStringRoot>> m_entryList = new List<KeyValuePair<HySStringRoot, HySStringRoot>>();

        /// <summary><para>method outline:</para>
        /// <para>アーカイブ対象ファイル取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> AddEntry(KeyValuePair entry) </para>
        /// </example>
        /// <param name="entry">エントリ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void AddEntry(KeyValuePair<HySStringRoot, HySStringRoot> entry)
        {
            m_entryList.Add(entry);
        }

        /// <summary><para>method outline:</para>
        /// <para>アーカイブ対象ファイル取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> AddEntry(List entries) </para>
        /// </example>
        /// <param name="entries">エントリ情報リスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void AddEntry(List<KeyValuePair<HySStringRoot, HySStringRoot>> entries)
        {
            foreach (KeyValuePair<HySStringRoot, HySStringRoot> entry in entries)
            {
                AddEntry(entry);
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>登録済みエントリの返却</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetEntry(); </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>entryList　エントリ情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public List<KeyValuePair<HySStringRoot,HySStringRoot>> GetEntry()
        {
            return new List<KeyValuePair<HySStringRoot, HySStringRoot>>(m_entryList);
        }

        /// <summary><para>method outline:</para>
        /// <para>アーカイブ実行</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Archive(HySStringRoot archiveFileFullPath); </para>
        /// </example>
        /// <param name="archiveFileFullPath">圧縮用ファイルフルパス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void Archive(HySStringRoot archiveFileFullPath)
        {
            try
            {
                ZipFile csZip = new ZipFile(System.Text.Encoding.GetEncoding("shift_jis"));
                foreach (KeyValuePair<HySStringRoot, HySStringRoot> entry in m_entryList)
                {
                    // ArchiveImplメソッドを呼び出す
                    ArchiveImpl(ref csZip, entry);
                }
                csZip.Save(archiveFileFullPath.ToString());
            }
            catch (Ionic.Zip.ZipException Exp)
            {
                HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "Archive", Exp.ToString());
                throw Exp;
            }
            finally
            {

            }
            # region J# 固有処理
            //java.io.FileOutputStream fileOutPutStream =
            //    new java.io.FileOutputStream(archiveFileFullPath.ToString());
            //java.util.zip.ZipOutputStream zipOutPutStream =
            //    new java.util.zip.ZipOutputStream(fileOutPutStream);

            //try
            //{
            //    foreach (KeyValuePair<HySStringRoot, HySStringRoot> entry in m_entryList)
            //    {
            //        // ArchiveImplメソッドを呼び出す
            //        ArchiveImpl(ref zipOutPutStream, entry);
            //    }
            //}
            //catch (java.util.zip.ZipException Exp)
            //{
            //    HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "Archive", Exp.ToString());
            //    throw Exp;
            //}
            //catch (java.io.IOException Exp)
            //{
            //    HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "Archive", Exp.ToString());
            //    throw Exp;
            //}
            //finally
            //{
            //    zipOutPutStream.close();
            //    fileOutPutStream.close();
            //}
            # endregion
        }

        /// <summary><para>method outline:</para>
        /// <para>エントリ情報の書き込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ArchiveImpl(ZipFile csZip, KeyValuePair entry); </para>
        /// </example>
        /// <param name="csZip">Zip入出力クラス</param>
        /// <param name="entry">エントリ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void ArchiveImpl(ref ZipFile csZip, KeyValuePair<HySStringRoot, HySStringRoot> entry)
        {
            string entryName;
            string dataFullPath;

            try
            {
                FormatEntryName(entry, out entryName, out dataFullPath);
                // エントリ名の修正(パスからディレクトリ部分のみに修正)
                string NewEntryName = Path.GetDirectoryName(entryName);
                // 圧縮レベルの設定
                csZip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
                // ディレクトリかどうかの判定
                if (Directory.Exists(dataFullPath) == true)
                {
                    // エントリ登録(ソース含みの場合,空のbin,objフォルダ生成処理)
                    // 空のフォルダ作成
                    csZip.AddDirectoryByName(NewEntryName);
                }
                else
                {
                    // エントリ登録
                    csZip.AddFile(dataFullPath, NewEntryName);
                }
            }
            catch (Ionic.Zip.ZipException Exp)
            {
                HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "ArchiveImpl", Exp.ToString());
                throw Exp;
            }
            finally
            {
                
            }
        }

        # region J# 固有処理
        ///// <summary><para>method outline:</para>
        ///// <para>エントリ情報の書き込み</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para> ArchiveImpl(java.util.zip.ZipOutputStream zipOutputStream, KeyValuePair entry); </para>
        ///// </example>
        ///// <param name="zipOutputStream">Zipアウトプットストリーム</param>
        ///// <param name="entry">エントリ情報</param>
        ///// <returns>無し</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para>無し</para>
        ///// </remarks>
        //protected void ArchiveImpl(ref java.util.zip.ZipOutputStream zipOutputStream, KeyValuePair<HySStringRoot, HySStringRoot> entry)
        //{
        //    string entryName;
        //    string dataFullPath;

        //    try
        //    {
        //        FormatEntryName(entry, out entryName, out dataFullPath);
        //        java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(entryName);
        //        // アーカイブ方法を指定する
        //        zipEntry.setMethod(java.util.zip.ZipEntry.DEFLATED);

        //        // エントリ登録
        //        zipOutputStream.putNextEntry(zipEntry);
        //        if (!zipEntry.isDirectory())
        //        {
        //            java.io.FileInputStream fileInputStream = new java.io.FileInputStream(dataFullPath);
        //            sbyte[] buffer = new sbyte[8192];
        //            int len;
        //            try
        //            {
        //                while ((len = fileInputStream.read(buffer, 0, buffer.Length)) > 0)
        //                {
        //                    zipOutputStream.write(buffer, 0, len);
        //                }
        //            }
        //            finally
        //            {
        //                fileInputStream.close();
        //            }
        //        }
        //    }
        //    catch (java.util.zip.ZipException Exp)
        //    {
        //        HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "ArchiveImpl", Exp.ToString());
        //        throw Exp;
        //    }
        //    catch (java.io.IOException Exp)
        //    {
        //        HySLog.LogOut(HySLog.ONLINE, "HySDotNetZipArchiver", "ArchiveImpl", Exp.ToString());
        //        throw Exp;
        //    }
        //    finally
        //    {
        //        zipOutputStream.closeEntry();
        //    }
        //}   
        # endregion

        /// <summary><para>method outline:</para>
        /// <para>エントリ体裁整理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>FormatEntryName(KeyValuePair entry,out string entryName,out string dataFullPath); </para>
        /// </example>
        /// <param name="entry">エントリリスト</param>
        /// <param name="entryName">エントリ名</param>
        /// <param name="dataFullPath">エントリパス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void FormatEntryName(KeyValuePair<HySStringRoot, HySStringRoot> entry,out string entryName,out string dataFullPath)
        {
            // エントリ名を取り出す
            string entryName_work = entry.Key.ToString();
            // ファイルパスを取り出す
            string dataFullPath_work = entry.Value.ToString();

            // dataFullPath_workがディレクトリかファイルのどちらかであるかの判定
            if (Directory.Exists(dataFullPath_work) == false && File.Exists(dataFullPath_work) == false )
            {
                throw new System.IO.FileNotFoundException("dataFullPath_workはファイルでもフォルダでもありません" );
            }

            // dataFullPath_workがディレクトリかどうかの判定
            if (Directory.Exists(dataFullPath_work) == true)
            {
                // 末尾に/を挿入
                entryName_work = entryName_work + "/";
            }

            entryName = entryName_work;
            dataFullPath = dataFullPath_work;

        }
    }
}

