package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.AbstractStateHolder;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import org.apache.logging.log4j.LogManager;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.util.StringUtil;
import java.util.Random;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelReader;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import org.apache.logging.log4j.Logger;

public class CommandBlock extends BaseEntityBlock {
    private static final Logger LOGGER;
    public static final DirectionProperty FACING;
    public static final BooleanProperty CONDITIONAL;
    
    public CommandBlock(final Properties c) {
        super(c);
        this.registerDefaultState((((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)CommandBlock.FACING, Direction.NORTH)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, false));
    }
    
    @Override
    public BlockEntity newBlockEntity(final BlockGetter bjg) {
        final CommandBlockEntity bwq3 = new CommandBlockEntity();
        bwq3.setAutomatic(this == Blocks.CHAIN_COMMAND_BLOCK);
        return bwq3;
    }
    
    @Override
    public void neighborChanged(final BlockState byj, final Level bjw, final BlockPos fk3, final Block bph, final BlockPos fk5, final boolean boolean6) {
        if (bjw.isClientSide) {
            return;
        }
        final BlockEntity bwl8 = bjw.getBlockEntity(fk3);
        if (!(bwl8 instanceof CommandBlockEntity)) {
            return;
        }
        final CommandBlockEntity bwq9 = (CommandBlockEntity)bwl8;
        final boolean boolean7 = bjw.hasNeighborSignal(fk3);
        final boolean boolean8 = bwq9.isPowered();
        bwq9.setPowered(boolean7);
        if (boolean8 || bwq9.isAutomatic() || bwq9.getMode() == CommandBlockEntity.Mode.SEQUENCE) {
            return;
        }
        if (boolean7) {
            bwq9.markConditionMet();
            bjw.getBlockTicks().scheduleTick(fk3, this, this.getTickDelay(bjw));
        }
    }
    
    @Override
    public void tick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
        final BlockEntity bwl6 = xd.getBlockEntity(fk);
        if (bwl6 instanceof CommandBlockEntity) {
            final CommandBlockEntity bwq7 = (CommandBlockEntity)bwl6;
            final BaseCommandBlock bjc8 = bwq7.getCommandBlock();
            final boolean boolean9 = !StringUtil.isNullOrEmpty(bjc8.getCommand());
            final CommandBlockEntity.Mode a10 = bwq7.getMode();
            final boolean boolean10 = bwq7.wasConditionMet();
            if (a10 == CommandBlockEntity.Mode.AUTO) {
                bwq7.markConditionMet();
                if (boolean10) {
                    this.execute(byj, xd, fk, bjc8, boolean9);
                }
                else if (bwq7.isConditional()) {
                    bjc8.setSuccessCount(0);
                }
                if (bwq7.isPowered() || bwq7.isAutomatic()) {
                    xd.getBlockTicks().scheduleTick(fk, this, this.getTickDelay(xd));
                }
            }
            else if (a10 == CommandBlockEntity.Mode.REDSTONE) {
                if (boolean10) {
                    this.execute(byj, xd, fk, bjc8, boolean9);
                }
                else if (bwq7.isConditional()) {
                    bjc8.setSuccessCount(0);
                }
            }
            xd.updateNeighbourForOutputSignal(fk, this);
        }
    }
    
    private void execute(final BlockState byj, final Level bjw, final BlockPos fk, final BaseCommandBlock bjc, final boolean boolean5) {
        if (boolean5) {
            bjc.performCommand(bjw);
        }
        else {
            bjc.setSuccessCount(0);
        }
        executeChain(bjw, fk, byj.<Direction>getValue((Property<Direction>)CommandBlock.FACING));
    }
    
    @Override
    public int getTickDelay(final LevelReader bjz) {
        return 1;
    }
    
    @Override
    public InteractionResult use(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        final BlockEntity bwl8 = bjw.getBlockEntity(fk);
        if (bwl8 instanceof CommandBlockEntity && ayj.canUseGameMasterBlocks()) {
            ayj.openCommandBlock((CommandBlockEntity)bwl8);
            return InteractionResult.SUCCESS;
        }
        return InteractionResult.PASS;
    }
    
    @Override
    public boolean hasAnalogOutputSignal(final BlockState byj) {
        return true;
    }
    
    @Override
    public int getAnalogOutputSignal(final BlockState byj, final Level bjw, final BlockPos fk) {
        final BlockEntity bwl5 = bjw.getBlockEntity(fk);
        if (bwl5 instanceof CommandBlockEntity) {
            return ((CommandBlockEntity)bwl5).getCommandBlock().getSuccessCount();
        }
        return 0;
    }
    
    @Override
    public void setPlacedBy(final Level bjw, final BlockPos fk, final BlockState byj, final LivingEntity akz, final ItemStack ben) {
        final BlockEntity bwl7 = bjw.getBlockEntity(fk);
        if (!(bwl7 instanceof CommandBlockEntity)) {
            return;
        }
        final CommandBlockEntity bwq8 = (CommandBlockEntity)bwl7;
        final BaseCommandBlock bjc9 = bwq8.getCommandBlock();
        if (ben.hasCustomHoverName()) {
            bjc9.setName(ben.getHoverName());
        }
        if (!bjw.isClientSide) {
            if (ben.getTagElement("BlockEntityTag") == null) {
                bjc9.setTrackOutput(bjw.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK));
                bwq8.setAutomatic(this == Blocks.CHAIN_COMMAND_BLOCK);
            }
            if (bwq8.getMode() == CommandBlockEntity.Mode.SEQUENCE) {
                final boolean boolean10 = bjw.hasNeighborSignal(fk);
                bwq8.setPowered(boolean10);
            }
        }
    }
    
    @Override
    public RenderShape getRenderShape(final BlockState byj) {
        return RenderShape.MODEL;
    }
    
    @Override
    public BlockState rotate(final BlockState byj, final Rotation btu) {
        return ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Direction>setValue((Property<Comparable>)CommandBlock.FACING, btu.rotate(byj.<Direction>getValue((Property<Direction>)CommandBlock.FACING)));
    }
    
    @Override
    public BlockState mirror(final BlockState byj, final Mirror bsu) {
        return byj.rotate(bsu.getRotation(byj.<Direction>getValue((Property<Direction>)CommandBlock.FACING)));
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(CommandBlock.FACING, CommandBlock.CONDITIONAL);
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        return ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)CommandBlock.FACING, bcq.getNearestLookingDirection().getOpposite());
    }
    
    private static void executeChain(final Level bjw, final BlockPos fk, Direction fp) {
        final BlockPos.MutableBlockPos a4 = new BlockPos.MutableBlockPos(fk);
        final GameRules bjs5 = bjw.getGameRules();
        int integer6 = bjs5.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH);
        while (integer6-- > 0) {
            a4.move(fp);
            final BlockState byj7 = bjw.getBlockState(a4);
            final Block bph8 = byj7.getBlock();
            if (bph8 != Blocks.CHAIN_COMMAND_BLOCK) {
                break;
            }
            final BlockEntity bwl9 = bjw.getBlockEntity(a4);
            if (!(bwl9 instanceof CommandBlockEntity)) {
                break;
            }
            final CommandBlockEntity bwq10 = (CommandBlockEntity)bwl9;
            if (bwq10.getMode() != CommandBlockEntity.Mode.SEQUENCE) {
                break;
            }
            if (bwq10.isPowered() || bwq10.isAutomatic()) {
                final BaseCommandBlock bjc11 = bwq10.getCommandBlock();
                if (bwq10.markConditionMet()) {
                    if (!bjc11.performCommand(bjw)) {
                        break;
                    }
                    bjw.updateNeighbourForOutputSignal(a4, bph8);
                }
                else if (bwq10.isConditional()) {
                    bjc11.setSuccessCount(0);
                }
            }
            fp = byj7.<Direction>getValue((Property<Direction>)CommandBlock.FACING);
        }
        if (integer6 <= 0) {
            final int integer7 = Math.max(bjs5.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH), 0);
            CommandBlock.LOGGER.warn("Command Block chain tried to execute more than {} steps!", integer7);
        }
    }
    
    static {
        LOGGER = LogManager.getLogger();
        FACING = DirectionalBlock.FACING;
        CONDITIONAL = BlockStateProperties.CONDITIONAL;
    }
}
