package code.util

import java.io._
import org.apache.commons.compress.archivers.zip.{ZipArchiveEntry, ZipArchiveOutputStream}
import code.util.Util.using

/**
 * Zip 形式でアーカイブするためのユーティリティクラスです。
 */
class ZipCompresser(base: File) {

  /**
   * 基準になるディレクトリかファイル
   */
  private var baseFile: File = base

  /**
   * 起点になるディレクトリ（ファイル）の絶対パス
   */
  private var baseFilePath: String = base.getAbsolutePath

  /**
   * baseFile を圧縮します。
   */
  def archive: Unit = {
    val zipfile: File = new File(this.baseFile.getParent, this.baseFile.getName + ".zip")
    using(new ZipArchiveOutputStream(new FileOutputStream(zipfile))) { zos =>
      zos.setEncoding("Windows-31J")
      archive(zos, this.baseFile)
    }
  }

  /**
   * file を zos に出力します。
   *
   * @param zos zipファイル出力ストリーム
   * @param file 入力元ファイル
   */
  private def archive(zos: ZipArchiveOutputStream, file: File): Unit = {
    if (file.isDirectory) {
      for (f <- file.listFiles) {
        archive(zos, f)
      }
    } else {
      using(new BufferedInputStream(new FileInputStream(file))){ fis =>
        val entryName = file.getAbsolutePath.replace(this.baseFilePath, "").substring(1)
        zos.putArchiveEntry(new ZipArchiveEntry(entryName))
        
        var ava: Int = 0
        while ({ava = fis.available; ava} > 0) {
          val bs = new Array[Byte](ava)
          fis.read(bs)
          zos.write(bs)
        }
        zos.closeArchiveEntry
      }
    }
    
  }
}