package net.minecraft.world.level;

import com.mojang.brigadier.context.CommandContext;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerLevel;
import java.util.Date;
import javax.annotation.Nullable;
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 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;
    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) ? new TextComponent("") : this.lastOutput;
    }
    
    public CompoundTag save(final CompoundTag jt) {
        jt.putString("Command", this.command);
        jt.putInt("SuccessCount", this.successCount);
        jt.putString("CustomName", Component.Serializer.toJson(this.name));
        jt.putBoolean("TrackOutput", this.trackOutput);
        if (this.lastOutput != null && this.trackOutput) {
            jt.putString("LastOutput", Component.Serializer.toJson(this.lastOutput));
        }
        jt.putBoolean("UpdateLastExecution", this.updateLastExecution);
        if (this.updateLastExecution && this.lastExecution > 0L) {
            jt.putLong("LastExecution", this.lastExecution);
        }
        return jt;
    }
    
    public void load(final CompoundTag jt) {
        this.command = jt.getString("Command");
        this.successCount = jt.getInt("SuccessCount");
        if (jt.contains("CustomName", 8)) {
            this.setName(Component.Serializer.fromJson(jt.getString("CustomName")));
        }
        if (jt.contains("TrackOutput", 1)) {
            this.trackOutput = jt.getBoolean("TrackOutput");
        }
        if (jt.contains("LastOutput", 8) && this.trackOutput) {
            try {
                this.lastOutput = Component.Serializer.fromJson(jt.getString("LastOutput"));
            }
            catch (Throwable throwable3) {
                this.lastOutput = new TextComponent(throwable3.getMessage());
            }
        }
        else {
            this.lastOutput = null;
        }
        if (jt.contains("UpdateLastExecution")) {
            this.updateLastExecution = jt.getBoolean("UpdateLastExecution");
        }
        if (this.updateLastExecution && jt.contains("LastExecution")) {
            this.lastExecution = jt.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 bjw) {
        if (bjw.isClientSide || bjw.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 != null && minecraftServer3.isInitialized() && minecraftServer3.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) {
            try {
                this.lastOutput = null;
                final CommandSourceStack cq4 = this.createCommandSourceStack().withCallback((ResultConsumer<CommandSourceStack>)((commandContext, boolean2, integer) -> {
                    if (boolean2) {
                        ++this.successCount;
                    }
                }));
                minecraftServer3.getCommands().performCommand(cq4, this.command);
            }
            catch (Throwable throwable4) {
                final CrashReport h5 = CrashReport.forThrowable(throwable4, "Executing command block");
                final CrashReportCategory i6 = h5.addCategory("Command to be executed");
                i6.setDetail("Command", this::getCommand);
                i6.setDetail("Name", () -> this.getName().getString());
                throw new ReportedException(h5);
            }
        }
        if (this.updateLastExecution) {
            this.lastExecution = bjw.getGameTime();
        }
        else {
            this.lastExecution = -1L;
        }
        return true;
    }
    
    public Component getName() {
        return this.name;
    }
    
    public void setName(@Nullable final Component lf) {
        if (lf != null) {
            this.name = lf;
        }
        else {
            this.name = BaseCommandBlock.DEFAULT_NAME;
        }
    }
    
    @Override
    public void sendMessage(final Component lf) {
        if (this.trackOutput) {
            this.lastOutput = new TextComponent("[" + BaseCommandBlock.TIME_FORMAT.format(new Date()) + "] ").append(lf);
            this.onUpdated();
        }
    }
    
    public abstract ServerLevel getLevel();
    
    public abstract void onUpdated();
    
    public void setLastOutput(@Nullable final Component lf) {
        this.lastOutput = lf;
    }
    
    public void setTrackOutput(final boolean boolean1) {
        this.trackOutput = boolean1;
    }
    
    public boolean isTrackOutput() {
        return this.trackOutput;
    }
    
    public boolean usedBy(final Player ayj) {
        if (!ayj.canUseGameMasterBlocks()) {
            return false;
        }
        if (ayj.getCommandSenderWorld().isClientSide) {
            ayj.openMinecartCommandBlock(this);
        }
        return true;
    }
    
    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("@");
    }
}
