package com.qmai.android.plugin

import java.io.*
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream


object ZipUtils1 {
    private const val BUFFER_SIZE = 2 * 1024

    /**
     * zip解压
     * @param srcFile        zip源文件
     * @param destDirPath     解压后的目标文件夹
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    @Throws(RuntimeException::class)
    fun unZip(srcFile: File, destDirPath: String) {
        val start = System.currentTimeMillis()
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw RuntimeException(srcFile.getPath().toString() + "所指文件不存在")
        }
        // 开始解压
        var zipFile: ZipFile? = null
        try {
            zipFile = ZipFile(srcFile)
            val entries: Enumeration<*> = zipFile.entries()
           /* while (zipFile.entries().hasMoreElements()){
                val entry: ZipEntry = entries.nextElement() as ZipEntry
                println("解压: " + entry.getName())
            }*/
            while (entries.hasMoreElements()) {
                val entry: ZipEntry = entries.nextElement() as ZipEntry
                println("解压" + entry.getName())
                val name = entry.name
                //__MACOSX/SophixPatchTool_macos/._.DS_Store
                if (name.contains("__MACOSX")||name.contains("/.DS_Store")){
                    continue
                }
                // 如果是文件夹，就创建个文件夹
                if (entry.isDirectory()) {
                    val dirPath = destDirPath + "/" + entry.getName()
                    val dir = File(dirPath)
                    dir.mkdirs()
                } else {
                    // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                    val targetFile = File(destDirPath + "/" + entry.getName())
                    // 保证这个文件的父文件夹必须要存在
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs()
                    }
                    targetFile.createNewFile()
                    // 将压缩文件内容写入到这个文件中
                    val `is`: InputStream = zipFile.getInputStream(entry)
                    val fos = FileOutputStream(targetFile)
                    var len: Int = 0
                    val buf = ByteArray(BUFFER_SIZE)
                    while (`is`.read(buf).also({ len = it }) != -1) {
                        fos.write(buf, 0, len)
                    }
                    // 关流顺序，先打开的后关闭
                    fos.close()
                    `is`.close()
                }
            }
            val end = System.currentTimeMillis()
            println("解压完成，耗时：" + (end - start) + " ms")
        } catch (e: Exception) {
           println("uzip error = $e")
            throw RuntimeException("unzip error from ZipUtils", e)
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
    }

    /**
     * 压缩成ZIP 方法
     * @param srcFiles 需要压缩的文件列表
     * @param out           压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    @Throws(Exception::class)
    fun toZip(srcFiles: List<File>, out: OutputStream?) {
        val start = System.currentTimeMillis()
        var zos: ZipOutputStream? = null
        try {
            zos = ZipOutputStream(out)
            for (srcFile in srcFiles) {
                val buf = ByteArray(BUFFER_SIZE)
                zos.putNextEntry(ZipEntry(srcFile.getName()))
                var len: Int
                val `in` = FileInputStream(srcFile)
                while (`in`.read(buf).also { len = it } != -1) {
                    zos.write(buf, 0, len)
                }
                zos.closeEntry()
                `in`.close()
            }
            val end = System.currentTimeMillis()
            println("压缩完成，耗时：" + (end - start) + " ms")
        } catch (e: Exception) {
            throw RuntimeException("zip error from ZipUtils", e)
        } finally {
            if (zos != null) {
                try {
                    zos.close()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }
}