package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.AbstractStateHolder;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.StateDefinition;
import java.util.Random;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.TickPriority;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import javax.annotation.Nullable;
import java.util.List;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ComparatorBlockEntity;
import net.minecraft.core.BlockPos;
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.ComparatorMode;
import net.minecraft.world.level.block.state.properties.EnumProperty;

public class ComparatorBlock extends DiodeBlock implements EntityBlock {
    public static final EnumProperty<ComparatorMode> MODE;
    
    public ComparatorBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)ComparatorBlock.FACING, Direction.NORTH)).setValue((Property<Comparable>)ComparatorBlock.POWERED, false)).<ComparatorMode, ComparatorMode>setValue(ComparatorBlock.MODE, ComparatorMode.COMPARE));
    }
    
    @Override
    protected int getDelay(final BlockState byj) {
        return 2;
    }
    
    @Override
    protected int getOutputSignal(final BlockGetter bjg, final BlockPos fk, final BlockState byj) {
        final BlockEntity bwl5 = bjg.getBlockEntity(fk);
        if (bwl5 instanceof ComparatorBlockEntity) {
            return ((ComparatorBlockEntity)bwl5).getOutputSignal();
        }
        return 0;
    }
    
    private int calculateOutputSignal(final Level bjw, final BlockPos fk, final BlockState byj) {
        if (byj.<ComparatorMode>getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT) {
            return Math.max(this.getInputSignal(bjw, fk, byj) - this.getAlternateSignal(bjw, fk, byj), 0);
        }
        return this.getInputSignal(bjw, fk, byj);
    }
    
    @Override
    protected boolean shouldTurnOn(final Level bjw, final BlockPos fk, final BlockState byj) {
        final int integer5 = this.getInputSignal(bjw, fk, byj);
        if (integer5 == 0) {
            return false;
        }
        final int integer6 = this.getAlternateSignal(bjw, fk, byj);
        return integer5 > integer6 || (integer5 == integer6 && byj.<ComparatorMode>getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE);
    }
    
    @Override
    protected int getInputSignal(final Level bjw, final BlockPos fk, final BlockState byj) {
        int integer5 = super.getInputSignal(bjw, fk, byj);
        final Direction fp6 = byj.<Direction>getValue((Property<Direction>)ComparatorBlock.FACING);
        BlockPos fk2 = fk.relative(fp6);
        BlockState byj2 = bjw.getBlockState(fk2);
        if (byj2.hasAnalogOutputSignal()) {
            integer5 = byj2.getAnalogOutputSignal(bjw, fk2);
        }
        else if (integer5 < 15 && byj2.isRedstoneConductor(bjw, fk2)) {
            fk2 = fk2.relative(fp6);
            byj2 = bjw.getBlockState(fk2);
            if (byj2.hasAnalogOutputSignal()) {
                integer5 = byj2.getAnalogOutputSignal(bjw, fk2);
            }
            else if (byj2.isAir()) {
                final ItemFrame avr9 = this.getItemFrame(bjw, fp6, fk2);
                if (avr9 != null) {
                    integer5 = avr9.getAnalogOutput();
                }
            }
        }
        return integer5;
    }
    
    @Nullable
    private ItemFrame getItemFrame(final Level bjw, final Direction fp, final BlockPos fk) {
        final List<ItemFrame> list5 = bjw.<ItemFrame>getEntitiesOfClass(ItemFrame.class, new AABB(fk.getX(), fk.getY(), fk.getZ(), fk.getX() + 1, fk.getY() + 1, fk.getZ() + 1), avr -> avr != null && avr.getDirection() == fp);
        if (list5.size() == 1) {
            return list5.get(0);
        }
        return null;
    }
    
    @Override
    public InteractionResult use(BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        if (!ayj.abilities.mayBuild) {
            return InteractionResult.PASS;
        }
        byj = ((AbstractStateHolder<O, BlockState>)byj).<ComparatorMode>cycle(ComparatorBlock.MODE);
        final float float8 = (byj.<ComparatorMode>getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT) ? 0.55f : 0.5f;
        bjw.playSound(ayj, fk, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3f, float8);
        bjw.setBlock(fk, byj, 2);
        this.refreshOutputState(bjw, fk, byj);
        return InteractionResult.SUCCESS;
    }
    
    @Override
    protected void checkTickOnNeighbor(final Level bjw, final BlockPos fk, final BlockState byj) {
        if (bjw.getBlockTicks().willTickThisTick(fk, this)) {
            return;
        }
        final int integer5 = this.calculateOutputSignal(bjw, fk, byj);
        final BlockEntity bwl6 = bjw.getBlockEntity(fk);
        final int integer6 = (bwl6 instanceof ComparatorBlockEntity) ? ((ComparatorBlockEntity)bwl6).getOutputSignal() : 0;
        if (integer5 != integer6 || byj.<Boolean>getValue((Property<Boolean>)ComparatorBlock.POWERED) != this.shouldTurnOn(bjw, fk, byj)) {
            final TickPriority bkn8 = this.shouldPrioritize(bjw, fk, byj) ? TickPriority.HIGH : TickPriority.NORMAL;
            bjw.getBlockTicks().scheduleTick(fk, this, 2, bkn8);
        }
    }
    
    private void refreshOutputState(final Level bjw, final BlockPos fk, final BlockState byj) {
        final int integer5 = this.calculateOutputSignal(bjw, fk, byj);
        final BlockEntity bwl6 = bjw.getBlockEntity(fk);
        int integer6 = 0;
        if (bwl6 instanceof ComparatorBlockEntity) {
            final ComparatorBlockEntity bwr8 = (ComparatorBlockEntity)bwl6;
            integer6 = bwr8.getOutputSignal();
            bwr8.setOutputSignal(integer5);
        }
        if (integer6 != integer5 || byj.<ComparatorMode>getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE) {
            final boolean boolean8 = this.shouldTurnOn(bjw, fk, byj);
            final boolean boolean9 = byj.<Boolean>getValue((Property<Boolean>)ComparatorBlock.POWERED);
            if (boolean9 && !boolean8) {
                bjw.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)ComparatorBlock.POWERED, false), 2);
            }
            else if (!boolean9 && boolean8) {
                bjw.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)ComparatorBlock.POWERED, true), 2);
            }
            this.updateNeighborsInFront(bjw, fk, byj);
        }
    }
    
    @Override
    public void tick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
        this.refreshOutputState(xd, fk, byj);
    }
    
    @Override
    public boolean triggerEvent(final BlockState byj, final Level bjw, final BlockPos fk, final int integer4, final int integer5) {
        super.triggerEvent(byj, bjw, fk, integer4, integer5);
        final BlockEntity bwl7 = bjw.getBlockEntity(fk);
        return bwl7 != null && bwl7.triggerEvent(integer4, integer5);
    }
    
    @Override
    public BlockEntity newBlockEntity(final BlockGetter bjg) {
        return new ComparatorBlockEntity();
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(ComparatorBlock.FACING, ComparatorBlock.MODE, ComparatorBlock.POWERED);
    }
    
    static {
        MODE = BlockStateProperties.MODE_COMPARATOR;
    }
}
