package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.pathfinder.PathComputationType;
import java.util.Iterator;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.entity.EntityType;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import java.util.Random;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.level.DefaultExplosionDamageCalculator;
import java.util.Optional;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import java.util.function.Function;
import net.minecraft.core.Direction;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.tags.Tag;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ItemStack;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.server.level.ServerPlayer;
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.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.properties.IntegerProperty;

public class RespawnAnchorBlock extends Block {
    public static final IntegerProperty CHARGE;
    
    public RespawnAnchorBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((StateHolder<O, BlockState>)this.stateDefinition.any()).<Comparable, Integer>setValue((Property<Comparable>)RespawnAnchorBlock.CHARGE, 0));
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        final ItemStack bki8 = bec.getItemInHand(anf);
        if (anf == InteractionHand.MAIN_HAND && !isRespawnFuel(bki8) && isRespawnFuel(bec.getItemInHand(InteractionHand.OFF_HAND))) {
            return InteractionResult.PASS;
        }
        if (isRespawnFuel(bki8) && canBeCharged(cfj)) {
            charge(bqb, fu, cfj);
            if (!bec.abilities.instabuild) {
                bki8.shrink(1);
            }
            return InteractionResult.sidedSuccess(bqb.isClientSide);
        }
        if (cfj.<Integer>getValue((Property<Integer>)RespawnAnchorBlock.CHARGE) == 0) {
            return InteractionResult.PASS;
        }
        if (canSetSpawn(bqb)) {
            if (!bqb.isClientSide) {
                final ServerPlayer ze9 = (ServerPlayer)bec;
                if (ze9.getRespawnDimension() != bqb.dimension() || !ze9.getRespawnPosition().equals(fu)) {
                    ze9.setRespawnPosition(bqb.dimension(), fu, false, true);
                    bqb.playSound(null, fu.getX() + 0.5, fu.getY() + 0.5, fu.getZ() + 0.5, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0f, 1.0f);
                    return InteractionResult.SUCCESS;
                }
            }
            return InteractionResult.CONSUME;
        }
        if (!bqb.isClientSide) {
            this.explode(cfj, bqb, fu);
        }
        return InteractionResult.sidedSuccess(bqb.isClientSide);
    }
    
    private static boolean isRespawnFuel(final ItemStack bki) {
        return bki.getItem() == Items.GLOWSTONE;
    }
    
    private static boolean canBeCharged(final BlockState cfj) {
        return cfj.<Integer>getValue((Property<Integer>)RespawnAnchorBlock.CHARGE) < 4;
    }
    
    private static boolean isWaterThatWouldFlow(final BlockPos fu, final Level bqb) {
        final FluidState cxa3 = bqb.getFluidState(fu);
        if (!cxa3.is(FluidTags.WATER)) {
            return false;
        }
        if (cxa3.isSource()) {
            return true;
        }
        final float float4 = (float)cxa3.getAmount();
        if (float4 < 2.0f) {
            return false;
        }
        final FluidState cxa4 = bqb.getFluidState(fu.below());
        return !cxa4.is(FluidTags.WATER);
    }
    
    private void explode(final BlockState cfj, final Level bqb, final BlockPos fu) {
        bqb.removeBlock(fu, false);
        final boolean boolean5 = Direction.Plane.HORIZONTAL.stream().map(fu::relative).anyMatch(fu -> isWaterThatWouldFlow(fu, bqb));
        final boolean boolean6 = boolean5 || bqb.getFluidState(fu.above()).is(FluidTags.WATER);
        final ExplosionDamageCalculator bpu7 = new ExplosionDamageCalculator() {
            @Override
            public Optional<Float> getBlockExplosionResistance(final Explosion bpt, final BlockGetter bpg, final BlockPos fu, final BlockState cfj, final FluidState cxa) {
                if (fu.equals(fu) && boolean6) {
                    return Optional.<Float>of(Blocks.WATER.getExplosionResistance());
                }
                return DefaultExplosionDamageCalculator.INSTANCE.getBlockExplosionResistance(bpt, bpg, fu, cfj, cxa);
            }
            
            @Override
            public boolean shouldBlockExplode(final Explosion bpt, final BlockGetter bpg, final BlockPos fu, final BlockState cfj, final float float5) {
                return DefaultExplosionDamageCalculator.INSTANCE.shouldBlockExplode(bpt, bpg, fu, cfj, float5);
            }
        };
        bqb.explode(null, DamageSource.badRespawnPointExplosion(), bpu7, fu.getX() + 0.5, fu.getY() + 0.5, fu.getZ() + 0.5, 5.0f, true, Explosion.BlockInteraction.DESTROY);
    }
    
    public static boolean canSetSpawn(final Level bqb) {
        return bqb.dimensionType().respawnAnchorWorks();
    }
    
    public static void charge(final Level bqb, final BlockPos fu, final BlockState cfj) {
        bqb.setBlock(fu, ((StateHolder<O, BlockState>)cfj).<Comparable, Integer>setValue((Property<Comparable>)RespawnAnchorBlock.CHARGE, cfj.<Integer>getValue((Property<Integer>)RespawnAnchorBlock.CHARGE) + 1), 3);
        bqb.playSound(null, fu.getX() + 0.5, fu.getY() + 0.5, fu.getZ() + 0.5, SoundEvents.RESPAWN_ANCHOR_CHARGE, SoundSource.BLOCKS, 1.0f, 1.0f);
    }
    
    @Override
    public void animateTick(final BlockState cfj, final Level bqb, final BlockPos fu, final Random random) {
        if (cfj.<Integer>getValue((Property<Integer>)RespawnAnchorBlock.CHARGE) == 0) {
            return;
        }
        if (random.nextInt(100) == 0) {
            bqb.playSound(null, fu.getX() + 0.5, fu.getY() + 0.5, fu.getZ() + 0.5, SoundEvents.RESPAWN_ANCHOR_AMBIENT, SoundSource.BLOCKS, 1.0f, 1.0f);
        }
        final double double6 = fu.getX() + 0.5 + (0.5 - random.nextDouble());
        final double double7 = fu.getY() + 1.0;
        final double double8 = fu.getZ() + 0.5 + (0.5 - random.nextDouble());
        final double double9 = random.nextFloat() * 0.04;
        bqb.addParticle(ParticleTypes.REVERSE_PORTAL, double6, double7, double8, 0.0, double9, 0.0);
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(RespawnAnchorBlock.CHARGE);
    }
    
    @Override
    public boolean hasAnalogOutputSignal(final BlockState cfj) {
        return true;
    }
    
    public static int getScaledChargeLevel(final BlockState cfj, final int integer) {
        return Mth.floor((cfj.<Integer>getValue((Property<Integer>)RespawnAnchorBlock.CHARGE) - 0) / 4.0f * integer);
    }
    
    @Override
    public int getAnalogOutputSignal(final BlockState cfj, final Level bqb, final BlockPos fu) {
        return getScaledChargeLevel(cfj, 15);
    }
    
    public static Optional<Vec3> findStandUpPosition(final EntityType<?> aoq, final LevelReader bqd, final BlockPos fu) {
        for (final BlockPos fu2 : BlockPos.betweenClosed(fu.offset(-1, -1, -1), fu.offset(1, 1, 1))) {
            final Optional<Vec3> optional6 = BedBlock.getStandingLocationAtOrBelow(aoq, bqd, fu2);
            if (optional6.isPresent()) {
                return optional6;
            }
        }
        return Optional.<Vec3>empty();
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        return false;
    }
    
    static {
        CHARGE = BlockStateProperties.RESPAWN_ANCHOR_CHARGES;
    }
}
