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

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

import com.hypixel.hytale.server.core.universe.PlayerRef;
import javax.annotation.Nullable;
import java.util.Comparator;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.BasicFileAttributes;
import com.hypixel.hytale.server.core.permissions.PermissionsModule;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.protocol.packets.interface_.WorldSavingStatus;
import com.hypixel.hytale.server.core.universe.Universe;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.CRC32;
import java.nio.file.LinkOption;
import java.nio.file.FileVisitOption;
import com.hypixel.hytale.common.util.java.ManifestUtil;
import java.util.zip.ZipOutputStream;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import javax.annotation.Nonnull;
import java.nio.file.Path;

class BackupUtil
{
    static void walkFileTreeAndZip(@Nonnull final Path sourceDir, @Nonnull final Path zipPath) throws IOException {
        final ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipPath, new OpenOption[0]));
        try {
            zipOutputStream.setMethod(0);
            zipOutputStream.setLevel(0);
            zipOutputStream.setComment("Automated backup by HytaleServer - Version: " + ManifestUtil.getImplementationVersion() + ", Revision: " + ManifestUtil.getImplementationRevisionId());
            try (final Stream<Path> stream = Files.walk(sourceDir, new FileVisitOption[0])) {
                final List<Path> files = stream.filter(x$0 -> Files.isRegularFile(x$0, new LinkOption[0])).toList();
                for (final Path path : files) {
                    final long size = Files.size(path);
                    final CRC32 crc = new CRC32();
                    try (final InputStream inputStream = Files.newInputStream(path, new OpenOption[0])) {
                        final byte[] buffer = new byte[16384];
                        int len;
                        while ((len = inputStream.read(buffer)) != -1) {
                            crc.update(buffer, 0, len);
                        }
                    }
                    final ZipEntry zipEntry = new ZipEntry(sourceDir.relativize(path).toString());
                    zipEntry.setSize(size);
                    zipEntry.setCompressedSize(size);
                    zipEntry.setCrc(crc.getValue());
                    zipOutputStream.putNextEntry(zipEntry);
                    Files.copy(path, zipOutputStream);
                    zipOutputStream.closeEntry();
                }
            }
            zipOutputStream.close();
        }
        catch (final Throwable t3) {
            try {
                zipOutputStream.close();
            }
            catch (final Throwable exception3) {
                t3.addSuppressed(exception3);
            }
            throw t3;
        }
    }
    
    static void broadcastBackupStatus(final boolean isWorldSaving) {
        Universe.get().broadcastPacket(new WorldSavingStatus(isWorldSaving));
    }
    
    static void broadcastBackupError(final Throwable cause) {
        final Message message = Message.translation("server.universe.backup.error").param("message", cause.getLocalizedMessage());
        Universe.get().getPlayers().forEach(player -> {
            final boolean hasPermission = PermissionsModule.get().hasPermission(player.getUuid(), "hytale.status.backup.error");
            if (hasPermission) {
                player.sendMessage(message);
            }
        });
    }
    
    @Nullable
    static List<Path> findOldBackups(@Nonnull final Path backupDirectory, final int maxBackupCount) throws IOException {
        if (!backupDirectory.toFile().isDirectory()) {
            return null;
        }
        try (final Stream<Path> files = Files.list(backupDirectory)) {
            final List<Path> zipFiles = files.filter(p -> p.getFileName().toString().endsWith(".zip")).sorted(Comparator.comparing(p -> {
                try {
                    return Files.readAttributes(p, BasicFileAttributes.class, new LinkOption[0]).creationTime();
                }
                catch (final IOException e) {
                    return FileTime.fromMillis(0L);
                }
            })).toList();
            if (zipFiles.size() > maxBackupCount) {
                final List<Path> subList = zipFiles.subList(0, zipFiles.size() - maxBackupCount);
                if (files != null) {
                    files.close();
                }
                return subList;
            }
        }
        return null;
    }
}
