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

package com.hypixel.hytale.server.core.modules.collision.commands;

import com.hypixel.hytale.assetstore.JsonAsset;
import java.util.Iterator;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
import java.util.Collection;
import com.hypixel.hytale.server.core.util.message.MessageFormat;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Arrays;
import java.util.Set;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import com.hypixel.hytale.server.core.command.system.CommandContext;
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.RequiredArg;
import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase;
import com.hypixel.hytale.server.core.Message;
import javax.annotation.Nonnull;
import com.hypixel.hytale.math.shape.Box;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractCommandCollection;

public class HitboxCommand extends AbstractCommandCollection
{
    public HitboxCommand() {
        super("hitbox", "server.commands.hitbox.desc");
        this.addSubCommand(new HitboxExtentsCommand());
        this.addUsageVariant(new HitboxGetCommand());
    }
    
    @Nonnull
    private static Message formatBox(@Nonnull final Box box) {
        return Message.translation("server.commands.hitbox.box").param("minX", box.min.x).param("minY", box.min.y).param("minZ", box.min.z).param("maxX", box.max.x).param("maxY", box.max.y).param("maxZ", box.max.z);
    }
    
    private static class HitboxGetCommand extends CommandBase
    {
        @Nonnull
        private final RequiredArg<String> hitboxArg;
        
        public HitboxGetCommand() {
            super("server.commands.hitbox.desc");
            this.hitboxArg = this.withRequiredArg("hitbox", "server.commands.hitbox.hitbox.desc", ArgTypes.STRING);
        }
        
        @Override
        protected void executeSync(@Nonnull final CommandContext context) {
            final String name = this.hitboxArg.get(context);
            final BlockBoundingBoxes boundingBox = BlockBoundingBoxes.getAssetMap().getAsset(name);
            if (boundingBox != null) {
                final BlockBoundingBoxes.RotatedVariantBoxes rotated = boundingBox.get(Rotation.None, Rotation.None, Rotation.None);
                context.sendMessage(Message.translation("server.commands.hitbox.boundingBox").param("box", HitboxCommand.formatBox(rotated.getBoundingBox())));
                final Box[] details = rotated.getDetailBoxes();
                if (details.length > 0) {
                    final Message header = Message.translation("server.commands.hitbox.details.header");
                    final Set<Message> detailMessages = Arrays.stream(details).map((Function<? super Box, ?>)HitboxCommand::formatBox).collect((Collector<? super Object, ?, Set<Message>>)Collectors.toSet());
                    context.sendMessage(MessageFormat.list(header, detailMessages));
                }
            }
            else {
                context.sendMessage(Message.translation("server.commands.hitbox.notFound").param("name", name));
            }
        }
    }
    
    private static class HitboxExtentsCommand extends CommandBase
    {
        @Nonnull
        private final OptionalArg<Double> thresholdArg;
        
        public HitboxExtentsCommand() {
            super("extents", "server.commands.hitbox.extents.desc");
            this.thresholdArg = this.withOptionalArg("threshold", "server.commands.hitbox.extents.threshold.desc", ArgTypes.DOUBLE);
        }
        
        @Override
        protected void executeSync(@Nonnull final CommandContext context) {
            final BlockTypeAssetMap<String, BlockType> blockTypeAssetMap = BlockType.getAssetMap();
            final IndexedLookupTableAssetMap<String, BlockBoundingBoxes> boundingBoxAssetMap = BlockBoundingBoxes.getAssetMap();
            int totalNumberOfFillerBlocks = 0;
            final double threshold = this.thresholdArg.provided(context) ? this.thresholdArg.get(context) : 0.5;
            for (final BlockType blockType : blockTypeAssetMap.getAssetMap().values()) {
                final Box boundingBox = boundingBoxAssetMap.getAsset(blockType.getHitboxTypeIndex()).get(0).getBoundingBox();
                final double width = boundingBox.width();
                final double height = boundingBox.height();
                final double depth = boundingBox.depth();
                int blockWidth = Math.max(MathUtil.floor(width), 1);
                int blockHeight = Math.max(MathUtil.floor(height), 1);
                int blockDepth = Math.max(MathUtil.floor(depth), 1);
                if (width - blockWidth > threshold) {
                    ++blockWidth;
                }
                if (height - blockHeight > threshold) {
                    ++blockHeight;
                }
                if (depth - blockDepth > threshold) {
                    ++blockDepth;
                }
                final int numberOfBlocks = blockWidth * blockHeight * blockDepth;
                final int numberOfFillerBlocks = numberOfBlocks - 1;
                totalNumberOfFillerBlocks += numberOfFillerBlocks;
            }
            context.sendMessage(Message.translation("server.commands.hitbox.extentsThresholdNeeded").param("threshold", threshold).param("nb", totalNumberOfFillerBlocks));
        }
    }
}
