/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.util;

/**
 * Работа с архивами и сжатием
 */
public class ArchiveHelper {

    /**
     * Заархивировать массив байт алгоритмом GZip
     * @param dat исходный массив
     * @return заархивированый массив
     */
    public static byte[] compressGZip(byte[] dat) throws Exception, java.io.IOException {
        try (com.pullenti.unisharp.MemoryStream res = new com.pullenti.unisharp.MemoryStream()) {
            try (com.pullenti.unisharp.MemoryStream input = new com.pullenti.unisharp.MemoryStream(dat)) {
                input.setPosition(0L);
                try (com.pullenti.unisharp.GZipStream deflate = new com.pullenti.unisharp.GZipStream(res, true)) {
                    input.writeTo(deflate);
                    deflate.flush();
                    deflate.close();
                }
            }
            return res.toByteArray();
        }
    }

    /**
     * Разархивировать байтовый массив алгоритмом GZip
     * @param zip архивированный массив
     * @return результат
     */
    public static byte[] decompressGZip(byte[] zip) throws Exception, java.io.IOException {
        try (com.pullenti.unisharp.MemoryStream data = new com.pullenti.unisharp.MemoryStream(zip)) {
            data.setPosition(0L);
            try (com.pullenti.unisharp.MemoryStream unzip = new com.pullenti.unisharp.MemoryStream()) {
                byte[] buf = new byte[zip.length + zip.length];
                try (com.pullenti.unisharp.GZipStream deflate = new com.pullenti.unisharp.GZipStream(data, false)) {
                    while (true) {
                        int i = -1;
                        try {
                            for (int ii = 0; ii < buf.length; ii++) {
                                buf[ii] = (byte)0;
                            }
                            i = deflate.read(buf, 0, buf.length);
                        } catch (Exception ex) {
                            for (i = buf.length - 1; i >= 0; i--) {
                                if (buf[i] != ((byte)0)) {
                                    unzip.write(buf, 0, i + 1);
                                    break;
                                }
                            }
                            break;
                        }
                        if (i < 1) 
                            break;
                        unzip.write(buf, 0, i);
                    }
                }
                byte[] res = unzip.toByteArray();
                return res;
            }
        }
    }

    /**
     * Заархивировать байтовый массив алгоритмом Zlib
     * @param dat исходный массив
     * @return заархивированый массив
     */
    public static byte[] compressZlib(byte[] dat) throws Exception, java.io.IOException {
        try (com.pullenti.unisharp.MemoryStream res = new com.pullenti.unisharp.MemoryStream()) {
            try (com.pullenti.unisharp.MemoryStream input = new com.pullenti.unisharp.MemoryStream(dat)) {
                input.setPosition(0L);
                try (com.pullenti.unisharp.DeflateStream deflate = new com.pullenti.unisharp.DeflateStream(res, true, true)) {
                    input.writeTo(deflate);
                    deflate.flush();
                }
            }
            return res.toByteArray();
        }
    }

    /**
     * Разархивировать байтовый массив алгоритмом Zlib.
     * @param zip архивированный массив
     * @return результат
     */
    public static byte[] decompressZlib(byte[] zip) throws Exception, java.io.IOException {
        if (zip == null || (zip.length < 4)) 
            return null;
        try (com.pullenti.unisharp.MemoryStream unzip = new com.pullenti.unisharp.MemoryStream()) {
            byte[] buf = new byte[zip.length + zip.length];
            try (com.pullenti.unisharp.MemoryStream data = new com.pullenti.unisharp.MemoryStream(zip)) {
                data.setPosition(0L);
                try (com.pullenti.unisharp.DeflateStream deflate = new com.pullenti.unisharp.DeflateStream(data, false, true)) {
                    while (true) {
                        int i = deflate.read(buf, 0, buf.length);
                        if (i < 1) 
                            break;
                        unzip.write(buf, 0, i);
                    }
                }
                return unzip.toByteArray();
            }
        }
    }

    /**
     * Заархивировать байтовый массив алгоритмом Deflate (без Zlib-заголовка)
     * @param dat исходный массив
     * @return заархивированый массив
     */
    public static byte[] compressDeflate(byte[] dat) throws Exception, java.io.IOException {
        byte[] zip = null;
        try (com.pullenti.unisharp.MemoryStream res = new com.pullenti.unisharp.MemoryStream()) {
            try (com.pullenti.unisharp.MemoryStream input = new com.pullenti.unisharp.MemoryStream(dat)) {
                input.setPosition(0L);
                try (com.pullenti.unisharp.DeflateStream deflate = new com.pullenti.unisharp.DeflateStream(res, true, false)) {
                    input.writeTo(deflate);
                    deflate.flush();
                }
            }
            zip = res.toByteArray();
        }
        return zip;
    }

    /**
     * Разархивировать байтовый массив алгоритмом Deflate (без Zlib-заголовка)
     * @param zip архивированный массив
     * @return результат
     */
    public static byte[] decompressDeflate(byte[] zip) throws Exception, java.io.IOException {
        if (zip == null || (zip.length < 1)) 
            return null;
        try (com.pullenti.unisharp.MemoryStream unzip = new com.pullenti.unisharp.MemoryStream()) {
            int len = zip.length + zip.length;
            if (len > 10000000) 
                len = 10000000;
            byte[] buf = new byte[len];
            try (com.pullenti.unisharp.MemoryStream data = new com.pullenti.unisharp.MemoryStream(zip)) {
                data.setPosition(0L);
                try (com.pullenti.unisharp.DeflateStream deflate = new com.pullenti.unisharp.DeflateStream(data, false, false)) {
                    while (true) {
                        int i = deflate.read(buf, 0, buf.length);
                        if (i < 1) 
                            break;
                        unzip.write(buf, 0, i);
                    }
                }
                return unzip.toByteArray();
            }
        }
    }

    /**
     * Создать zip в потоке
     * @param res результирующий поток
     * @param files файлы для архивирования
     */
    public static void createZipStream(com.pullenti.unisharp.Stream res, java.util.ArrayList<FileInArchive> files) throws Exception, java.io.IOException {
        java.util.ArrayList<com.pullenti.unisharp.MemoryStream> streams = new java.util.ArrayList<com.pullenti.unisharp.MemoryStream>();
        try {
            try (com.pullenti.unitext.internal.zip.ZipFile zip = com.pullenti.unitext.internal.zip.ZipFile.createStream(res)) {
                zip.beginUpdate0();
                for (FileInArchive f : files) {
                    com.pullenti.unisharp.MemoryStream mem = new com.pullenti.unisharp.MemoryStream(f.content);
                    zip.addStream(mem, f.key);
                    streams.add(mem);
                }
                zip.commitUpdate();
            }
        } catch (Exception ex) {
            throw new Exception("ZIP Error: " + ex, ex);
        }
        for (com.pullenti.unisharp.MemoryStream m : streams) {
            m.close();
        }
    }

    /**
     * Создать zip-файл
     * @param resName результирующее имя архивного файла
     * @param files файлы для архивирования
     */
    public static void createZipFile(String resName, java.util.ArrayList<String> files) throws Exception {
        try {
            try (com.pullenti.unitext.internal.zip.ZipFile zip = com.pullenti.unitext.internal.zip.ZipFile.createFile(resName)) {
                zip.beginUpdate0();
                for (String f : files) {
                    zip.add(f, (new java.io.File(f)).getName());
                }
                zip.commitUpdate();
            }
        } catch (Exception ex) {
            throw new Exception("ZIP Error: " + ex, ex);
        }
    }

    /**
     * Разархивировать файлы из ZIP-архива
     * @param zipFile имя архива
     * @param outDir результирующая директория
     * @return список полных имён разархивированных файлов
     */
    public static java.util.ArrayList<String> unzipFiles(String zipFile, String outDir) throws Exception, java.io.FileNotFoundException, java.io.IOException {
        java.util.ArrayList<String> files = new java.util.ArrayList<String>();
        try (com.pullenti.unitext.internal.misc.MyZipFile zip = new com.pullenti.unitext.internal.misc.MyZipFile(zipFile, null)) {
            for (com.pullenti.unitext.internal.misc.MyZipEntry e : zip.entries) {
                if (e.isDirectory || e.encrypted || e.uncompressDataSize == 0) 
                    continue;
                byte[] dat = e.getData();
                if (dat == null) 
                    continue;
                String fname = (new java.io.File(outDir, (new java.io.File((new java.io.File(e.name)).getName())).getPath())).getPath();
                files.add(fname);
                com.pullenti.unisharp.Utils.writeAllBytes(fname, dat);
            }
        }
        return files;
    }

    /**
     * Получить список файлов, содержащихся в архиве (архив может быть ZIP, RAR, TAR и некоторые другие)
     * @param fileName имя архива
     * @param content содержимое файла (если null, то fileName - ссылка на локальный файл)
     * @return список файлов в виде словаря {имя файла, размер файла} или null, если не поддержано
     */
    public static java.util.HashMap<String, Integer> getFileNamesFromArchive(String fileName, byte[] content) throws Exception, java.io.FileNotFoundException, java.io.IOException {
        com.pullenti.unitext.FileFormat frm = FileFormatsHelper.analizeFileFormat(fileName, content);
        java.util.HashMap<String, Integer> res = new java.util.HashMap<String, Integer>();
        if ((frm == com.pullenti.unitext.FileFormat.ZIP || frm == com.pullenti.unitext.FileFormat.DOCX || frm == com.pullenti.unitext.FileFormat.XLSX) || frm == com.pullenti.unitext.FileFormat.ODT) {
            try (com.pullenti.unitext.internal.misc.MyZipFile zip = new com.pullenti.unitext.internal.misc.MyZipFile(fileName, content)) {
                for (com.pullenti.unitext.internal.misc.MyZipEntry e : zip.entries) {
                    if (e.isDirectory || e.encrypted || e.uncompressDataSize == 0) 
                        continue;
                    if (!res.containsKey(e.name)) 
                        res.put(e.name, e.compressDataSize);
                }
            }
            return res;
        }
        try {
            if (com.pullenti.unitext.UnitextService.EXTENSION != null) 
                return com.pullenti.unitext.UnitextService.EXTENSION.getFileNamesFromArchive(fileName, content);
        } catch (Exception ex) {
        }
        return null;
    }

    /**
     * Разархивировать файл архива (архив может быть ZIP, RAR, TAR и некоторые другие). 
     * Сами файлы на диск не записываются - всё в памяти.
     * @param fileName имя архива
     * @param content содержимое файла (если null, то fileName - ссылка на локальный файл)
     * @return список файлов FileInArchive или null, если не поддержано
     */
    public static java.util.ArrayList<FileInArchive> getFilesFromArchive(String fileName, byte[] content) throws Exception, java.io.FileNotFoundException, java.io.IOException {
        com.pullenti.unitext.FileFormat frm = FileFormatsHelper.analizeFileFormat(fileName, content);
        java.util.ArrayList<FileInArchive> res = new java.util.ArrayList<FileInArchive>();
        if ((frm == com.pullenti.unitext.FileFormat.ZIP || frm == com.pullenti.unitext.FileFormat.DOCX || frm == com.pullenti.unitext.FileFormat.XLSX) || frm == com.pullenti.unitext.FileFormat.ODT) {
            try (com.pullenti.unitext.internal.misc.MyZipFile zip = new com.pullenti.unitext.internal.misc.MyZipFile(fileName, content)) {
                for (com.pullenti.unitext.internal.misc.MyZipEntry e : zip.entries) {
                    if (e.isDirectory || e.encrypted || e.uncompressDataSize == 0) 
                        continue;
                    byte[] dat = e.getData();
                    res.add(FileInArchive._new650(e.name, dat));
                }
            }
            return res;
        }
        try {
            if (com.pullenti.unitext.UnitextService.EXTENSION != null) 
                return com.pullenti.unitext.UnitextService.EXTENSION.getFilesFromArchive(fileName, content);
        } catch (Exception ex) {
        }
        return null;
    }

    /**
     * Извлечь файл из архива (архив может быть ZIP, RAR, TAR и некоторые другие)
     * @param fileName имя архива
     * @param content содержимое файла (если null, то fileName - ссылка на локальный файл)
     * @param internalName внутреннее имя (то, которое возвращалось функцией GetFileNamesFromArchive)
     * @return разархивированный байтовый поток
     */
    public static byte[] getFileFromArchive(String fileName, byte[] content, String internalName) throws Exception, java.io.FileNotFoundException, java.io.IOException {
        com.pullenti.unitext.FileFormat frm = FileFormatsHelper.analizeFileFormat(fileName, content);
        if (frm == com.pullenti.unitext.FileFormat.ZIP || frm == com.pullenti.unitext.FileFormat.DOCX) {
            try (com.pullenti.unitext.internal.misc.MyZipFile zip = new com.pullenti.unitext.internal.misc.MyZipFile(fileName, content)) {
                for (com.pullenti.unitext.internal.misc.MyZipEntry e : zip.entries) {
                    if (e.isDirectory || e.encrypted || e.uncompressDataSize == 0) 
                        continue;
                    if (com.pullenti.unisharp.Utils.stringsNe(e.name, internalName)) 
                        continue;
                    return e.getData();
                }
            }
        }
        try {
            if (com.pullenti.unitext.UnitextService.EXTENSION != null) 
                return com.pullenti.unitext.UnitextService.EXTENSION.getFileFromArchive(fileName, content, internalName);
        } catch (Exception ex) {
        }
        return null;
    }
    public ArchiveHelper() {
    }
}
