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

package com.hypixel.hytale.server.core.update.command;

import com.hypixel.hytale.server.core.command.system.arguments.system.Argument;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CancellationException;
import com.hypixel.hytale.common.util.FormatUtil;
import java.util.concurrent.atomic.AtomicInteger;
import com.hypixel.hytale.common.util.java.ManifestUtil;
import com.hypixel.hytale.server.core.auth.ServerAuthManager;
import com.hypixel.hytale.server.core.update.UpdateService;
import com.hypixel.hytale.server.core.update.UpdateModule;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractAsyncCommand;

public class UpdateDownloadCommand extends AbstractAsyncCommand
{
    private static final Message MSG_NOT_AUTHENTICATED;
    private static final Message MSG_CHECK_FAILED;
    private static final Message MSG_NO_UPDATE;
    private static final Message MSG_DOWNLOAD_FAILED;
    private static final Message MSG_DOWNLOAD_COMPLETE;
    private static final Message MSG_DOWNLOAD_IN_PROGRESS;
    private static final Message MSG_INVALID_LAYOUT;
    private final FlagArg forceFlag;
    
    public UpdateDownloadCommand() {
        super("download", "server.commands.update.download.desc");
        this.forceFlag = this.withFlagArg("force", "server.commands.update.download.force.desc");
    }
    
    @Nonnull
    @Override
    protected CompletableFuture<Void> executeAsync(@Nonnull final CommandContext context) {
        final UpdateModule updateModule = UpdateModule.get();
        if (updateModule != null && updateModule.isDownloadInProgress()) {
            context.sendMessage(UpdateDownloadCommand.MSG_DOWNLOAD_IN_PROGRESS);
            return CompletableFuture.completedFuture((Void)null);
        }
        if (!UpdateService.isValidUpdateLayout() && !((Argument<Arg, Boolean>)this.forceFlag).get(context)) {
            context.sendMessage(UpdateDownloadCommand.MSG_INVALID_LAYOUT);
            return CompletableFuture.completedFuture((Void)null);
        }
        final ServerAuthManager authManager = ServerAuthManager.getInstance();
        if (!authManager.hasSessionToken()) {
            context.sendMessage(UpdateDownloadCommand.MSG_NOT_AUTHENTICATED);
            return CompletableFuture.completedFuture((Void)null);
        }
        final UpdateService updateService = new UpdateService();
        return updateService.checkForUpdate(UpdateService.getEffectivePatchline()).thenCompose(manifest -> {
            if (manifest == null) {
                context.sendMessage(UpdateDownloadCommand.MSG_CHECK_FAILED);
                return CompletableFuture.completedFuture((Object)null);
            }
            else {
                if (updateModule != null) {
                    updateModule.setLatestKnownVersion(manifest);
                }
                final String currentVersion = ManifestUtil.getImplementationVersion();
                if (currentVersion != null && currentVersion.equals(manifest.version)) {
                    context.sendMessage(UpdateDownloadCommand.MSG_NO_UPDATE);
                    return CompletableFuture.completedFuture((Object)null);
                }
                else if (updateModule != null && !updateModule.tryAcquireDownloadLock()) {
                    context.sendMessage(UpdateDownloadCommand.MSG_DOWNLOAD_IN_PROGRESS);
                    return CompletableFuture.completedFuture((Object)null);
                }
                else {
                    context.sendMessage(Message.translation("server.commands.update.downloading").param("version", manifest.version));
                    final AtomicInteger lastPercent = new AtomicInteger(-1);
                    final UpdateService.DownloadTask downloadTask = updateService.downloadUpdate(manifest, UpdateService.getStagingDir(), (percent, downloaded, total) -> {
                        if (updateModule != null) {
                            updateModule.updateDownloadProgress(downloaded, total);
                        }
                        final int rounded = percent / 10 * 10;
                        if (rounded > lastPercent.get()) {
                            lastPercent.set(rounded);
                            context.sendMessage(Message.translation("server.commands.update.download_progress").param("percent", String.valueOf(percent)).param("downloaded", FormatUtil.bytesToString(downloaded)).param("total", FormatUtil.bytesToString(total)));
                        }
                        return;
                    });
                    final CompletableFuture<Boolean> downloadFuture = downloadTask.future().whenComplete((success, error) -> {
                        if (updateModule != null) {
                            updateModule.releaseDownloadLock();
                        }
                        if (error instanceof CancellationException) {
                            UpdateService.deleteStagedUpdate();
                        }
                        else if (error != null || !Boolean.TRUE.equals(success)) {
                            context.sendMessage(UpdateDownloadCommand.MSG_DOWNLOAD_FAILED);
                            UpdateService.deleteStagedUpdate();
                        }
                        else {
                            context.sendMessage(UpdateDownloadCommand.MSG_DOWNLOAD_COMPLETE);
                        }
                        return;
                    });
                    if (updateModule != null) {
                        updateModule.setActiveDownload(downloadFuture, downloadTask.thread());
                    }
                    return downloadFuture.thenApply(v -> null);
                }
            }
        });
    }
    
    static {
        MSG_NOT_AUTHENTICATED = Message.translation("server.commands.update.not_authenticated");
        MSG_CHECK_FAILED = Message.translation("server.commands.update.check_failed");
        MSG_NO_UPDATE = Message.translation("server.commands.update.no_update");
        MSG_DOWNLOAD_FAILED = Message.translation("server.commands.update.download_failed");
        MSG_DOWNLOAD_COMPLETE = Message.translation("server.commands.update.download_complete");
        MSG_DOWNLOAD_IN_PROGRESS = Message.translation("server.commands.update.download_in_progress");
        MSG_INVALID_LAYOUT = Message.translation("server.commands.update.invalid_layout_download");
    }
}
