package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
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.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.BlockBehaviour;
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((((StateHolder<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 bpg) {
        final CommandBlockEntity cdq3 = new CommandBlockEntity();
        cdq3.setAutomatic(this == Blocks.CHAIN_COMMAND_BLOCK);
        return cdq3;
    }
    
    @Override
    public void neighborChanged(final BlockState cfj, final Level bqb, final BlockPos fu3, final Block bvr, final BlockPos fu5, final boolean boolean6) {
        if (bqb.isClientSide) {
            return;
        }
        final BlockEntity cdl8 = bqb.getBlockEntity(fu3);
        if (!(cdl8 instanceof CommandBlockEntity)) {
            return;
        }
        final CommandBlockEntity cdq9 = (CommandBlockEntity)cdl8;
        final boolean boolean7 = bqb.hasNeighborSignal(fu3);
        final boolean boolean8 = cdq9.isPowered();
        cdq9.setPowered(boolean7);
        if (boolean8 || cdq9.isAutomatic() || cdq9.getMode() == CommandBlockEntity.Mode.SEQUENCE) {
            return;
        }
        if (boolean7) {
            cdq9.markConditionMet();
            bqb.getBlockTicks().scheduleTick(fu3, this, 1);
        }
    }
    
    @Override
    public void tick(final BlockState cfj, final ServerLevel zd, final BlockPos fu, final Random random) {
        final BlockEntity cdl6 = zd.getBlockEntity(fu);
        if (cdl6 instanceof CommandBlockEntity) {
            final CommandBlockEntity cdq7 = (CommandBlockEntity)cdl6;
            final BaseCommandBlock bpc8 = cdq7.getCommandBlock();
            final boolean boolean9 = !StringUtil.isNullOrEmpty(bpc8.getCommand());
            final CommandBlockEntity.Mode a10 = cdq7.getMode();
            final boolean boolean10 = cdq7.wasConditionMet();
            if (a10 == CommandBlockEntity.Mode.AUTO) {
                cdq7.markConditionMet();
                if (boolean10) {
                    this.execute(cfj, zd, fu, bpc8, boolean9);
                }
                else if (cdq7.isConditional()) {
                    bpc8.setSuccessCount(0);
                }
                if (cdq7.isPowered() || cdq7.isAutomatic()) {
                    zd.getBlockTicks().scheduleTick(fu, this, 1);
                }
            }
            else if (a10 == CommandBlockEntity.Mode.REDSTONE) {
                if (boolean10) {
                    this.execute(cfj, zd, fu, bpc8, boolean9);
                }
                else if (cdq7.isConditional()) {
                    bpc8.setSuccessCount(0);
                }
            }
            zd.updateNeighbourForOutputSignal(fu, this);
        }
    }
    
    private void execute(final BlockState cfj, final Level bqb, final BlockPos fu, final BaseCommandBlock bpc, final boolean boolean5) {
        if (boolean5) {
            bpc.performCommand(bqb);
        }
        else {
            bpc.setSuccessCount(0);
        }
        executeChain(bqb, fu, cfj.<Direction>getValue((Property<Direction>)CommandBlock.FACING));
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        final BlockEntity cdl8 = bqb.getBlockEntity(fu);
        if (cdl8 instanceof CommandBlockEntity && bec.canUseGameMasterBlocks()) {
            bec.openCommandBlock((CommandBlockEntity)cdl8);
            return InteractionResult.sidedSuccess(bqb.isClientSide);
        }
        return InteractionResult.PASS;
    }
    
    @Override
    public boolean hasAnalogOutputSignal(final BlockState cfj) {
        return true;
    }
    
    @Override
    public int getAnalogOutputSignal(final BlockState cfj, final Level bqb, final BlockPos fu) {
        final BlockEntity cdl5 = bqb.getBlockEntity(fu);
        if (cdl5 instanceof CommandBlockEntity) {
            return ((CommandBlockEntity)cdl5).getCommandBlock().getSuccessCount();
        }
        return 0;
    }
    
    @Override
    public void setPlacedBy(final Level bqb, final BlockPos fu, final BlockState cfj, final LivingEntity aoy, final ItemStack bki) {
        final BlockEntity cdl7 = bqb.getBlockEntity(fu);
        if (!(cdl7 instanceof CommandBlockEntity)) {
            return;
        }
        final CommandBlockEntity cdq8 = (CommandBlockEntity)cdl7;
        final BaseCommandBlock bpc9 = cdq8.getCommandBlock();
        if (bki.hasCustomHoverName()) {
            bpc9.setName(bki.getHoverName());
        }
        if (!bqb.isClientSide) {
            if (bki.getTagElement("BlockEntityTag") == null) {
                bpc9.setTrackOutput(bqb.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK));
                cdq8.setAutomatic(this == Blocks.CHAIN_COMMAND_BLOCK);
            }
            if (cdq8.getMode() == CommandBlockEntity.Mode.SEQUENCE) {
                final boolean boolean10 = bqb.hasNeighborSignal(fu);
                cdq8.setPowered(boolean10);
            }
        }
    }
    
    @Override
    public RenderShape getRenderShape(final BlockState cfj) {
        return RenderShape.MODEL;
    }
    
    @Override
    public BlockState rotate(final BlockState cfj, final Rotation cap) {
        return ((StateHolder<O, BlockState>)cfj).<Comparable, Direction>setValue((Property<Comparable>)CommandBlock.FACING, cap.rotate(cfj.<Direction>getValue((Property<Direction>)CommandBlock.FACING)));
    }
    
    @Override
    public BlockState mirror(final BlockState cfj, final Mirror bzj) {
        return cfj.rotate(bzj.getRotation(cfj.<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 bin) {
        return ((StateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)CommandBlock.FACING, bin.getNearestLookingDirection().getOpposite());
    }
    
    private static void executeChain(final Level bqb, final BlockPos fu, Direction fz) {
        final BlockPos.MutableBlockPos a4 = fu.mutable();
        final GameRules bpx5 = bqb.getGameRules();
        int integer6 = bpx5.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH);
        while (integer6-- > 0) {
            a4.move(fz);
            final BlockState cfj7 = bqb.getBlockState(a4);
            final Block bvr8 = cfj7.getBlock();
            if (!cfj7.is(Blocks.CHAIN_COMMAND_BLOCK)) {
                break;
            }
            final BlockEntity cdl9 = bqb.getBlockEntity(a4);
            if (!(cdl9 instanceof CommandBlockEntity)) {
                break;
            }
            final CommandBlockEntity cdq10 = (CommandBlockEntity)cdl9;
            if (cdq10.getMode() != CommandBlockEntity.Mode.SEQUENCE) {
                break;
            }
            if (cdq10.isPowered() || cdq10.isAutomatic()) {
                final BaseCommandBlock bpc11 = cdq10.getCommandBlock();
                if (cdq10.markConditionMet()) {
                    if (!bpc11.performCommand(bqb)) {
                        break;
                    }
                    bqb.updateNeighbourForOutputSignal(a4, bvr8);
                }
                else if (cdq10.isConditional()) {
                    bpc11.setSuccessCount(0);
                }
            }
            fz = cfj7.<Direction>getValue((Property<Direction>)CommandBlock.FACING);
        }
        if (integer6 <= 0) {
            final int integer7 = Math.max(bpx5.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;
    }
}
