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

package com.hypixel.hytale.builtin.buildertools.commands;

import com.hypixel.hytale.server.core.command.system.arguments.system.Argument;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import java.util.regex.PatternSyntaxException;
import java.util.regex.Pattern;
import java.util.function.IntPredicate;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.hypixel.hytale.builtin.buildertools.utils.Material;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.builtin.buildertools.PrototypePlayerBuilderToolSettings;
import com.hypixel.hytale.server.core.entity.entities.Player;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Store;
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 com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;

public class ReplaceCommand extends AbstractPlayerCommand
{
    @Nonnull
    private final RequiredArg<BlockPattern> toArg;
    @Nonnull
    private final FlagArg substringSwapFlag;
    @Nonnull
    private final FlagArg regexFlag;
    
    public ReplaceCommand() {
        super("replace", "server.commands.replace.desc");
        this.toArg = this.withRequiredArg("to", "server.commands.replace.toBlock.desc", ArgTypes.BLOCK_PATTERN);
        this.substringSwapFlag = this.withFlagArg("substringSwap", "server.commands.replace.substringSwap.desc");
        this.regexFlag = this.withFlagArg("regex", "server.commands.replace.regex.desc");
        this.setPermissionGroup(GameMode.Creative);
        this.addUsageVariant(new ReplaceFromToCommand());
    }
    
    @Override
    protected void execute(@Nonnull final CommandContext context, @Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nonnull final World world) {
        executeReplace(context, store, ref, playerRef, null, this.toArg.get(context), ((Argument<Arg, Boolean>)this.substringSwapFlag).get(context), ((Argument<Arg, Boolean>)this.regexFlag).get(context));
    }
    
    private static void executeReplace(@Nonnull final CommandContext context, @Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nullable final String fromValue, @Nonnull final BlockPattern toPattern, final boolean substringSwap, final boolean regex) {
        final Player playerComponent = store.getComponent(ref, Player.getComponentType());
        assert playerComponent != null;
        if (!PrototypePlayerBuilderToolSettings.isOkayToDoCommandsOnSelection(ref, playerComponent, store)) {
            return;
        }
        if (toPattern == null || toPattern.isEmpty()) {
            context.sendMessage(Message.translation("server.builderTools.invalidBlockType").param("name", "").param("key", ""));
            return;
        }
        final String toValue = toPattern.toString();
        final Material fromMaterial = (fromValue != null) ? Material.fromKey(fromValue) : null;
        final Material toMaterial = Material.fromPattern(toPattern, ThreadLocalRandom.current());
        if (toMaterial.isFluid() && !substringSwap && !regex) {
            if (fromMaterial == null) {
                context.sendMessage(Message.translation("server.commands.replace.fromRequired"));
                return;
            }
            BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.replace(r, fromMaterial, toMaterial, componentAccessor));
            context.sendMessage(Message.translation("server.builderTools.replace.replacementBlockDone").param("from", fromValue).param("to", toValue));
        }
        else {
            if (fromMaterial != null && fromMaterial.isFluid()) {
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.replace(r, fromMaterial, toMaterial, componentAccessor));
                context.sendMessage(Message.translation("server.builderTools.replace.replacementBlockDone").param("from", fromValue).param("to", toValue));
                return;
            }
            final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
            if (fromValue == null && !substringSwap && !regex) {
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.replace(r, null, toPattern, componentAccessor));
                context.sendMessage(Message.translation("server.builderTools.replace.replacementAllDone").param("to", toValue));
                return;
            }
            if (fromValue == null) {
                context.sendMessage(Message.translation("server.commands.replace.fromRequired"));
                return;
            }
            if (regex) {
                Pattern pattern;
                try {
                    pattern = Pattern.compile(fromValue);
                }
                catch (final PatternSyntaxException e) {
                    context.sendMessage(Message.translation("server.commands.replace.invalidRegex").param("error", e.getMessage()));
                    return;
                }
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> {
                    s.replace(r, value -> {
                        final String valueKey = assetMap.getAsset(value).getId();
                        return pattern.matcher(valueKey).matches();
                    }, toPattern, componentAccessor);
                    context.sendMessage(Message.translation("server.commands.replace.success").param("regex", fromValue).param("replacement", toValue));
                });
                return;
            }
            if (fromMaterial == null) {
                context.sendMessage(Message.translation("server.builderTools.invalidBlockType").param("name", fromValue).param("key", fromValue));
                return;
            }
            if (substringSwap) {
                final String[] blockKeys = fromValue.split(",");
                final Int2IntArrayMap swapMap = new Int2IntArrayMap();
                for (int blockId = 0; blockId < assetMap.getAssetCount(); ++blockId) {
                    final BlockType blockType = assetMap.getAsset(blockId);
                    final String blockKeyStr = blockType.getId();
                    for (final String from : blockKeys) {
                        Label_0536: {
                            if (blockKeyStr.contains(from.trim())) {
                                String replacedKey;
                                try {
                                    replacedKey = blockKeyStr.replace(from.trim(), toValue);
                                }
                                catch (final Exception e2) {
                                    break Label_0536;
                                }
                                final int index = assetMap.getIndex(replacedKey);
                                if (index != Integer.MIN_VALUE) {
                                    swapMap.put(blockId, index);
                                    break;
                                }
                            }
                        }
                    }
                }
                if (!swapMap.isEmpty()) {
                    BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.replace(r, value -> swapMap.getOrDefault(value, value), componentAccessor));
                    context.sendMessage(Message.translation("server.builderTools.replace.replacementDone").param("nb", swapMap.size()).param("to", toValue));
                }
                else {
                    context.sendMessage(Message.translation("server.commands.replace.noMatchingBlocks").param("blockType", fromValue));
                }
                return;
            }
            final int fromBlockId = fromMaterial.getBlockId();
            BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.replace(r, block -> block == fromBlockId, toPattern, componentAccessor));
            context.sendMessage(Message.translation("server.builderTools.replace.replacementBlockDone").param("from", fromValue).param("to", toValue));
        }
    }
    
    private static class ReplaceFromToCommand extends AbstractPlayerCommand
    {
        @Nonnull
        private final RequiredArg<String> fromArg;
        @Nonnull
        private final RequiredArg<BlockPattern> toArg;
        @Nonnull
        private final FlagArg substringSwapFlag;
        @Nonnull
        private final FlagArg regexFlag;
        
        public ReplaceFromToCommand() {
            super("server.commands.replace.desc");
            this.fromArg = this.withRequiredArg("from", "server.commands.replace.from.desc", ArgTypes.STRING);
            this.toArg = this.withRequiredArg("to", "server.commands.replace.toBlock.desc", ArgTypes.BLOCK_PATTERN);
            this.substringSwapFlag = this.withFlagArg("substringSwap", "server.commands.replace.substringSwap.desc");
            this.regexFlag = this.withFlagArg("regex", "server.commands.replace.regex.desc");
            this.setPermissionGroup(GameMode.Creative);
        }
        
        @Override
        protected void execute(@Nonnull final CommandContext context, @Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref, @Nonnull final PlayerRef playerRef, @Nonnull final World world) {
            ReplaceCommand.executeReplace(context, store, ref, playerRef, this.fromArg.get(context), this.toArg.get(context), ((Argument<Arg, Boolean>)this.substringSwapFlag).get(context), ((Argument<Arg, Boolean>)this.regexFlag).get(context));
        }
    }
}
