// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.util.io;

import java.nio.file.StandardOpenOption;
import java.nio.file.StandardCopyOption;
import java.io.InputStream;
import java.util.function.Consumer;
import com.hypixel.hytale.sneakythrow.SneakyThrow;
import java.util.Comparator;
import java.util.stream.Stream;
import java.nio.file.CopyOption;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.attribute.FileAttribute;
import java.util.zip.ZipException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nonnull;
import java.nio.file.Path;
import java.util.regex.Pattern;
import java.nio.file.FileVisitOption;
import java.nio.file.OpenOption;
import java.util.Set;

public class FileUtil
{
    public static final Set<OpenOption> DEFAULT_WRITE_OPTIONS;
    public static final Set<FileVisitOption> DEFAULT_WALK_TREE_OPTIONS_SET;
    public static final FileVisitOption[] DEFAULT_WALK_TREE_OPTIONS_ARRAY;
    public static final Pattern INVALID_FILENAME_CHARACTERS;
    
    public static void unzipFile(@Nonnull final Path path, @Nonnull final byte[] buffer, @Nonnull final ZipInputStream zipStream, @Nonnull final ZipEntry zipEntry, @Nonnull final String name) throws IOException {
        final Path filePath = path.resolve(name);
        if (!filePath.toAbsolutePath().startsWith(path)) {
            throw new ZipException("Entry is outside of the target dir: " + zipEntry.getName());
        }
        if (zipEntry.isDirectory()) {
            Files.createDirectory(filePath, (FileAttribute<?>[])new FileAttribute[0]);
        }
        else {
            try (final OutputStream stream = Files.newOutputStream(filePath, new OpenOption[0])) {
                int len;
                while ((len = zipStream.read(buffer)) > 0) {
                    stream.write(buffer, 0, len);
                }
            }
        }
        zipStream.closeEntry();
    }
    
    public static void copyDirectory(@Nonnull final Path origin, @Nonnull final Path destination) throws IOException {
        try (final Stream<Path> paths = Files.walk(origin, new FileVisitOption[0])) {
            paths.forEach(originSubPath -> {
                try {
                    final Path relative = origin.relativize(originSubPath);
                    final Path destinationSubPath = destination.resolve(relative);
                    Files.copy(originSubPath, destinationSubPath, new CopyOption[0]);
                }
                catch (final Throwable t2) {
                    throw new RuntimeException("Error copying path", t2);
                }
                return;
            });
        }
    }
    
    public static void moveDirectoryContents(@Nonnull final Path origin, @Nonnull final Path destination, final CopyOption... options) throws IOException {
        try (final Stream<Path> paths = Files.walk(origin, new FileVisitOption[0])) {
            paths.forEach(originSubPath -> {
                if (originSubPath.equals(origin)) {
                    return;
                }
                else {
                    try {
                        final Path relative = origin.relativize(originSubPath);
                        final Path destinationSubPath = destination.resolve(relative);
                        Files.move(originSubPath, destinationSubPath, options);
                    }
                    catch (final Throwable t2) {
                        throw new RuntimeException("Error moving path", t2);
                    }
                    return;
                }
            });
        }
    }
    
    public static void deleteDirectory(@Nonnull final Path path) throws IOException {
        try (final Stream<Path> stream = Files.walk(path, new FileVisitOption[0])) {
            stream.sorted(Comparator.reverseOrder()).forEach(SneakyThrow.sneakyConsumer(Files::delete));
        }
    }
    
    public static void extractZip(@Nonnull final Path zipFile, @Nonnull final Path destDir) throws IOException {
        extractZip(Files.newInputStream(zipFile, new OpenOption[0]), destDir);
    }
    
    public static void extractZip(@Nonnull final InputStream inputStream, @Nonnull final Path destDir) throws IOException {
        try (final ZipInputStream zis = new ZipInputStream(inputStream)) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                final Path destPath = destDir.resolve(entry.getName()).normalize();
                if (!destPath.startsWith(destDir)) {
                    throw new ZipException("Zip entry outside target directory: " + entry.getName());
                }
                if (entry.isDirectory()) {
                    Files.createDirectories(destPath, (FileAttribute<?>[])new FileAttribute[0]);
                }
                else {
                    Files.createDirectories(destPath.getParent(), (FileAttribute<?>[])new FileAttribute[0]);
                    Files.copy(zis, destPath, StandardCopyOption.REPLACE_EXISTING);
                }
                zis.closeEntry();
            }
        }
    }
    
    static {
        DEFAULT_WRITE_OPTIONS = Set.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
        DEFAULT_WALK_TREE_OPTIONS_SET = Set.of();
        DEFAULT_WALK_TREE_OPTIONS_ARRAY = new FileVisitOption[0];
        INVALID_FILENAME_CHARACTERS = Pattern.compile("[<>:\"|?*/\\\\]");
    }
}
