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

package com.hypixel.hytale.server.npc.commands;

import com.hypixel.hytale.server.core.command.system.arguments.system.Argument;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import com.hypixel.hytale.server.npc.util.SensorSupportBenchmark;
import java.util.logging.Level;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import com.hypixel.hytale.common.benchmark.TimeDistributionRecorder;
import java.util.Formatter;
import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.codec.validation.Validators;
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.OptionalArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase;

public class NPCBenchmarkCommand extends CommandBase
{
    @Nonnull
    private static final Message MESSAGE_COMMANDS_NPC_BENCHMARK_START_FAILED;
    @Nonnull
    private static final Message MESSAGE_COMMANDS_NPC_BENCHMARK_DONE;
    @Nonnull
    private final FlagArg roleArg;
    @Nonnull
    private final FlagArg sensorSupportArg;
    @Nonnull
    private final OptionalArg<Double> secondsArg;
    
    public NPCBenchmarkCommand() {
        super("benchmark", "server.commands.npc.benchmark.desc");
        this.roleArg = this.withFlagArg("roles", "server.commands.npc.benchmark.role.desc");
        this.sensorSupportArg = this.withFlagArg("sensorsupport", "server.commands.npc.benchmark.sensor.desc");
        this.secondsArg = this.withOptionalArg("seconds", "server.commands.npc.benchmark.role.seconds", ArgTypes.DOUBLE).addValidator((Validator<Double>)Validators.greaterThan((DataType)0.0));
    }
    
    @Override
    protected void executeSync(@Nonnull final CommandContext context) {
        final double seconds = this.secondsArg.provided(context) ? this.secondsArg.get(context) : 30.0;
        boolean success;
        if (((Argument<Arg, Boolean>)this.roleArg).get(context)) {
            success = NPCPlugin.get().startRoleBenchmark(seconds, distribution -> {
                final StringBuilder sb = new StringBuilder().append("Role benchmark seconds=").append(seconds).append('\n');
                final Formatter formatter = new Formatter(sb);
                if (!distribution.isEmpty()) {
                    final TimeDistributionRecorder recorder = (TimeDistributionRecorder)distribution.get(-1);
                    recorder.formatHeader(formatter);
                    sb.append('\n');
                    final IntArrayList sortedIndices = new IntArrayList(distribution.keySet());
                    sortedIndices.rem(-1);
                    sortedIndices.sort((o1, o2) -> Double.compare(((TimeDistributionRecorder)distribution.get(o1)).getAverage(), ((TimeDistributionRecorder)distribution.get(o2)).getAverage()));
                    for (int i = 0; i < sortedIndices.size(); ++i) {
                        final int role = sortedIndices.getInt(i);
                        logRoleDistribution((TimeDistributionRecorder)distribution.get(role), sb, formatter, NPCPlugin.get().getName(role));
                    }
                    logRoleDistribution((TimeDistributionRecorder)distribution.get(-1), sb, formatter, "ALL");
                }
                context.sendMessage(NPCBenchmarkCommand.MESSAGE_COMMANDS_NPC_BENCHMARK_DONE);
                NPCPlugin.get().getLogger().at(Level.INFO).log(sb.toString());
                return;
            });
        }
        else {
            success = (((Argument<Arg, Boolean>)this.sensorSupportArg).get(context) && NPCPlugin.get().startSensorSupportBenchmark(seconds, sensorSupportData -> {
                final StringBuilder sb2 = new StringBuilder().append("PositionCache benchmark seconds=").append(seconds).append('\n');
                final Formatter formatter2 = new Formatter(sb2);
                if (!sensorSupportData.isEmpty()) {
                    final IntArrayList sortedIndices2 = new IntArrayList(sensorSupportData.keySet());
                    sortedIndices2.rem(-1);
                    sortedIndices2.sort((o1, o2) -> NPCPlugin.get().getName(o1).compareToIgnoreCase(NPCPlugin.get().getName(o2)));
                    final SensorSupportBenchmark data = (SensorSupportBenchmark)sensorSupportData.get(-1);
                    sb2.append("PositionCache Update Times\n");
                    data.formatHeaderUpdateTimes(formatter2);
                    sb2.append('\n');
                    for (int j = 0; j < sortedIndices2.size(); ++j) {
                        final int role2 = sortedIndices2.getInt(j);
                        final SensorSupportBenchmark bm = (SensorSupportBenchmark)sensorSupportData.get(role2);
                        if (bm.haveUpdateTimes()) {
                            logSensorSupportUpdateTime(bm, sb2, formatter2, NPCPlugin.get().getName(role2));
                        }
                    }
                    logSensorSupportUpdateTime((SensorSupportBenchmark)sensorSupportData.get(-1), sb2, formatter2, "ALL");
                    sb2.append("PositionCache Line of sight\n");
                    data.formatHeaderLoS(formatter2);
                    sb2.append('\n');
                    for (int k = 0; k < sortedIndices2.size(); ++k) {
                        final int role3 = sortedIndices2.getInt(k);
                        logSensorSupportLoS((SensorSupportBenchmark)sensorSupportData.get(role3), sb2, formatter2, NPCPlugin.get().getName(role3));
                    }
                    logSensorSupportLoS((SensorSupportBenchmark)sensorSupportData.get(-1), sb2, formatter2, "ALL");
                }
                context.sendMessage(NPCBenchmarkCommand.MESSAGE_COMMANDS_NPC_BENCHMARK_DONE);
                NPCPlugin.get().getLogger().at(Level.INFO).log(sb2.toString());
                return;
            }));
        }
        if (success) {
            context.sendMessage(Message.translation("server.commands.npc.benchmark.startedFor").param("seconds", seconds));
        }
        else {
            context.sendMessage(NPCBenchmarkCommand.MESSAGE_COMMANDS_NPC_BENCHMARK_START_FAILED);
        }
    }
    
    private static void logRoleDistribution(@Nonnull final TimeDistributionRecorder rec, @Nonnull final StringBuilder sb, @Nonnull final Formatter formatter, @Nonnull final String name) {
        rec.formatValues(formatter, 10000L);
        sb.append("|").append(name).append('\n');
    }
    
    private static void logSensorSupportUpdateTime(@Nonnull final SensorSupportBenchmark bm, @Nonnull final StringBuilder sb, @Nonnull final Formatter formatter, @Nonnull final String name) {
        bm.formatValuesUpdateTimePlayer(formatter);
        sb.append('|').append(name).append('\n');
        bm.formatValuesUpdateTimeEntity(formatter);
        sb.append('|').append(name).append('\n');
    }
    
    private static void logSensorSupportLoS(@Nonnull final SensorSupportBenchmark bm, @Nonnull final StringBuilder sb, @Nonnull final Formatter formatter, @Nonnull final String name) {
        if (bm.formatValuesLoS(formatter)) {
            sb.append('|').append(name).append('\n');
        }
    }
    
    static {
        MESSAGE_COMMANDS_NPC_BENCHMARK_START_FAILED = Message.translation("server.commands.npc.benchmark.startFailed");
        MESSAGE_COMMANDS_NPC_BENCHMARK_DONE = Message.translation("server.commands.npc.benchmark.done");
    }
}
