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

package com.hypixel.hytale.server.core.command.commands.debug;

import com.hypixel.hytale.common.util.StringUtil;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
import com.hypixel.hytale.server.core.command.system.arguments.system.DefaultArg;
import com.hypixel.hytale.metrics.metric.HistoricMetric;
import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.common.util.FormatUtil;
import java.util.concurrent.TimeUnit;
import com.hypixel.hytale.protocol.packets.connection.PongType;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.protocol.GameMode;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractTargetPlayerCommand;

public class PingCommand extends AbstractTargetPlayerCommand
{
    @Nonnull
    private final FlagArg detailFlag;
    
    public PingCommand() {
        super("ping", "server.commands.ping.desc");
        this.detailFlag = this.withFlagArg("detail", "server.commands.ping.detail.desc");
        this.setPermissionGroup(GameMode.Adventure);
        this.addSubCommand(new Clear());
        this.addSubCommand(new Graph());
    }
    
    @Override
    protected void execute(@Nonnull final CommandContext context, @Nullable final Ref<EntityStore> sourceRef, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nonnull final World world, @Nonnull final Store<EntityStore> store) {
        if (this.detailFlag.provided(context)) {
            this.sendDetailedMessage(context, playerRef);
        }
        else {
            this.sendShortMessage(context, playerRef);
        }
    }
    
    private void sendDetailedMessage(@Nonnull final CommandContext context, @Nonnull final PlayerRef playerRef) {
        final Message msg = Message.join(Message.raw(playerRef.getUsername()), Message.raw(" ping:"));
        final PongType[] values = PongType.values();
        for (int length2 = values.length, j = 0; j < length2; ++j) {
            final PongType pingType = values[j];
            final PacketHandler.PingInfo pingInfo = playerRef.getPacketHandler().getPingInfo(pingType);
            final HistoricMetric historicMetric = pingInfo.getPingMetricSet();
            final long[] periods = historicMetric.getPeriodsNanos();
            msg.insert(Message.raw("\n" + pingType.name() + ":\n"));
            for (int i = 0; i < periods.length; ++i) {
                final String length = FormatUtil.timeUnitToString(periods[i], TimeUnit.NANOSECONDS, true);
                final double average = historicMetric.getAverage(i);
                final long max = historicMetric.calculateMax(i);
                final long min = historicMetric.calculateMin(i);
                final String value = FormatUtil.simpleTimeUnitFormat(min, average, max, PacketHandler.PingInfo.TIME_UNIT, TimeUnit.MILLISECONDS, 3);
                msg.insert(Message.raw("  (" + length + "): " + " ".repeat(Math.max(0, 24 - value.length())) + value));
            }
            msg.insert(Message.raw("  Queue: " + FormatUtil.simpleFormat(pingInfo.getPacketQueueMetric())));
        }
        context.sendMessage(msg);
    }
    
    private void sendShortMessage(@Nonnull final CommandContext context, @Nonnull final PlayerRef playerRef) {
        final String length = FormatUtil.timeUnitToString(1L, TimeUnit.SECONDS, true);
        final Message msg = Message.join(Message.raw(playerRef.getUsername()), Message.raw(" ping  (" + length + "):"));
        final PongType[] values = PongType.values();
        for (int length2 = values.length, i = 0; i < length2; ++i) {
            final PongType pingType = values[i];
            final HistoricMetric historicMetric = playerRef.getPacketHandler().getPingInfo(pingType).getPingMetricSet();
            final double average = historicMetric.getAverage(0);
            final long max = historicMetric.calculateMax(0);
            final long min = historicMetric.calculateMin(0);
            final String value = FormatUtil.simpleTimeUnitFormat(min, average, max, PacketHandler.PingInfo.TIME_UNIT, TimeUnit.MILLISECONDS, 3);
            msg.insert(Message.raw("\n" + pingType.name() + ":" + " ".repeat(Math.max(0, 24 - value.length())) + value));
        }
        context.sendMessage(msg);
    }
    
    private static class Clear extends AbstractTargetPlayerCommand
    {
        @Nonnull
        private static final Message MESSAGE_COMMANDS_PING_HISTORY_CLEARED;
        
        public Clear() {
            super("clear", "server.commands.ping.clear.desc");
            this.setPermissionGroup(GameMode.Adventure);
            this.addAliases("reset");
        }
        
        @Override
        protected void execute(@Nonnull final CommandContext context, @Nullable final Ref<EntityStore> sourceRef, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nonnull final World world, @Nonnull final Store<EntityStore> store) {
            for (final PongType pingType : PongType.values()) {
                playerRef.getPacketHandler().getPingInfo(pingType).clear();
            }
            context.sendMessage(Clear.MESSAGE_COMMANDS_PING_HISTORY_CLEARED);
        }
        
        static {
            MESSAGE_COMMANDS_PING_HISTORY_CLEARED = Message.translation("server.commands.ping.historyCleared");
        }
    }
    
    private static class Graph extends AbstractTargetPlayerCommand
    {
        @Nonnull
        private final DefaultArg<Integer> widthArg;
        @Nonnull
        private final DefaultArg<Integer> heightArg;
        
        public Graph() {
            super("graph", "server.commands.ping.graph.desc");
            this.widthArg = this.withDefaultArg("width", "server.commands.ping.graph.width.desc", ArgTypes.INTEGER, 100, "server.commands.ping.graph.width.default");
            this.heightArg = this.withDefaultArg("height", "server.commands.ping.graph.height.desc", ArgTypes.INTEGER, 10, "server.commands.ping.graph.height.default");
            this.setPermissionGroup(GameMode.Adventure);
        }
        
        @Override
        protected void execute(@Nonnull final CommandContext context, @Nullable final Ref<EntityStore> sourceRef, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nonnull final World world, @Nonnull final Store<EntityStore> store) {
            final int width = this.widthArg.get(context);
            final int height = this.heightArg.get(context);
            final long startNanos = System.nanoTime();
            final Message message = Message.empty();
            final PongType[] values = PongType.values();
            for (int length = values.length, j = 0; j < length; ++j) {
                final PongType pingType = values[j];
                message.insert(String.valueOf(pingType) + ":\n");
                final PacketHandler.PingInfo pingInfo = playerRef.getPacketHandler().getPingInfo(pingType);
                final HistoricMetric pingMetricSet = pingInfo.getPingMetricSet();
                final long[] periods = pingMetricSet.getPeriodsNanos();
                for (int i = 0; i < periods.length; ++i) {
                    final long period = periods[i];
                    final long max = pingMetricSet.calculateMax(i);
                    final long min = pingMetricSet.calculateMin(i);
                    final long[] historyTimestamps = pingMetricSet.getTimestamps(i);
                    final long[] historyValues = pingMetricSet.getValues(i);
                    final String historyLengthFormatted = FormatUtil.timeUnitToString(period, TimeUnit.NANOSECONDS, true);
                    message.insert(Message.translation("server.commands.ping.graph.period").param("time", historyLengthFormatted));
                    final StringBuilder sb = new StringBuilder();
                    StringUtil.generateGraph(sb, width, height, startNanos - period, startNanos, (double)min, (double)max, value -> FormatUtil.timeUnitToString(MathUtil.fastCeil(value), PacketHandler.PingInfo.TIME_UNIT), historyTimestamps.length, ii -> historyTimestamps[ii], ii -> (double)historyValues[ii]);
                    message.insert(sb.toString());
                }
            }
            context.sendMessage(message);
        }
    }
}
