package net.minecraft.world.level;

import com.mojang.brigadier.context.CommandContext;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerLevel;
import java.util.Date;
import java.util.UUID;
import net.minecraft.CrashReportCategory;
import net.minecraft.server.MinecraftServer;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.ResultConsumer;
import net.minecraft.util.StringUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.TextComponent;
import javax.annotation.Nullable;
import net.minecraft.network.chat.Component;
import java.text.SimpleDateFormat;
import net.minecraft.commands.CommandSource;

public abstract class BaseCommandBlock implements CommandSource {
    private static final SimpleDateFormat TIME_FORMAT;
    private static final Component DEFAULT_NAME;
    private long lastExecution;
    private boolean updateLastExecution;
    private int successCount;
    private boolean trackOutput;
    @Nullable
    private Component lastOutput;
    private String command;
    private Component name;
    
    public BaseCommandBlock() {
        this.lastExecution = -1L;
        this.updateLastExecution = true;
        this.trackOutput = true;
        this.command = "";
        this.name = BaseCommandBlock.DEFAULT_NAME;
    }
    
    public int getSuccessCount() {
        return this.successCount;
    }
    
    public void setSuccessCount(final int integer) {
        this.successCount = integer;
    }
    
    public Component getLastOutput() {
        return (this.lastOutput == null) ? TextComponent.EMPTY : this.lastOutput;
    }
    
    public CompoundTag save(final CompoundTag le) {
        le.putString("Command", this.command);
        le.putInt("SuccessCount", this.successCount);
        le.putString("CustomName", Component.Serializer.toJson(this.name));
        le.putBoolean("TrackOutput", this.trackOutput);
        if (this.lastOutput != null && this.trackOutput) {
            le.putString("LastOutput", Component.Serializer.toJson(this.lastOutput));
        }
        le.putBoolean("UpdateLastExecution", this.updateLastExecution);
        if (this.updateLastExecution && this.lastExecution > 0L) {
            le.putLong("LastExecution", this.lastExecution);
        }
        return le;
    }
    
    public void load(final CompoundTag le) {
        this.command = le.getString("Command");
        this.successCount = le.getInt("SuccessCount");
        if (le.contains("CustomName", 8)) {
            this.setName(Component.Serializer.fromJson(le.getString("CustomName")));
        }
        if (le.contains("TrackOutput", 1)) {
            this.trackOutput = le.getBoolean("TrackOutput");
        }
        if (le.contains("LastOutput", 8) && this.trackOutput) {
            try {
                this.lastOutput = Component.Serializer.fromJson(le.getString("LastOutput"));
            }
            catch (Throwable throwable3) {
                this.lastOutput = new TextComponent(throwable3.getMessage());
            }
        }
        else {
            this.lastOutput = null;
        }
        if (le.contains("UpdateLastExecution")) {
            this.updateLastExecution = le.getBoolean("UpdateLastExecution");
        }
        if (this.updateLastExecution && le.contains("LastExecution")) {
            this.lastExecution = le.getLong("LastExecution");
        }
        else {
            this.lastExecution = -1L;
        }
    }
    
    public void setCommand(final String string) {
        this.command = string;
        this.successCount = 0;
    }
    
    public String getCommand() {
        return this.command;
    }
    
    public boolean performCommand(final Level bqb) {
        if (bqb.isClientSide || bqb.getGameTime() == this.lastExecution) {
            return false;
        }
        if ("Searge".equalsIgnoreCase(this.command)) {
            this.lastOutput = new TextComponent("#itzlipofutzli");
            this.successCount = 1;
            return true;
        }
        this.successCount = 0;
        final MinecraftServer minecraftServer3 = this.getLevel().getServer();
        if (minecraftServer3.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) {
            try {
                this.lastOutput = null;
                final CommandSourceStack cz4 = this.createCommandSourceStack().withCallback((ResultConsumer<CommandSourceStack>)((commandContext, boolean2, integer) -> {
                    if (boolean2) {
                        ++this.successCount;
                    }
                }));
                minecraftServer3.getCommands().performCommand(cz4, this.command);
            }
            catch (Throwable throwable4) {
                final CrashReport j5 = CrashReport.forThrowable(throwable4, "Executing command block");
                final CrashReportCategory k6 = j5.addCategory("Command to be executed");
                k6.setDetail("Command", this::getCommand);
                k6.setDetail("Name", () -> this.getName().getString());
                throw new ReportedException(j5);
            }
        }
        if (this.updateLastExecution) {
            this.lastExecution = bqb.getGameTime();
        }
        else {
            this.lastExecution = -1L;
        }
        return true;
    }
    
    public Component getName() {
        return this.name;
    }
    
    public void setName(@Nullable final Component mr) {
        if (mr != null) {
            this.name = mr;
        }
        else {
            this.name = BaseCommandBlock.DEFAULT_NAME;
        }
    }
    
    @Override
    public void sendMessage(final Component mr, final UUID uUID) {
        if (this.trackOutput) {
            this.lastOutput = new TextComponent("[" + BaseCommandBlock.TIME_FORMAT.format(new Date()) + "] ").append(mr);
            this.onUpdated();
        }
    }
    
    public abstract ServerLevel getLevel();
    
    public abstract void onUpdated();
    
    public void setLastOutput(@Nullable final Component mr) {
        this.lastOutput = mr;
    }
    
    public void setTrackOutput(final boolean boolean1) {
        this.trackOutput = boolean1;
    }
    
    public boolean isTrackOutput() {
        return this.trackOutput;
    }
    
    public InteractionResult usedBy(final Player bec) {
        if (!bec.canUseGameMasterBlocks()) {
            return InteractionResult.PASS;
        }
        if (bec.getCommandSenderWorld().isClientSide) {
            bec.openMinecartCommandBlock(this);
        }
        return InteractionResult.sidedSuccess(bec.level.isClientSide);
    }
    
    public abstract Vec3 getPosition();
    
    public abstract CommandSourceStack createCommandSourceStack();
    
    @Override
    public boolean acceptsSuccess() {
        return this.getLevel().getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK) && this.trackOutput;
    }
    
    @Override
    public boolean acceptsFailure() {
        return this.trackOutput;
    }
    
    @Override
    public boolean shouldInformAdmins() {
        return this.getLevel().getGameRules().getBoolean(GameRules.RULE_COMMANDBLOCKOUTPUT);
    }
    
    static {
        TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
        DEFAULT_NAME = new TextComponent("@");
    }
}
