package net.minecraft.world.level.pathfinder;

import javax.annotation.Nullable;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.tags.FluidTags;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;

public class SwimNodeEvaluator extends NodeEvaluator {
    private final boolean allowBreaching;
    
    public SwimNodeEvaluator(final boolean boolean1) {
        this.allowBreaching = boolean1;
    }
    
    @Override
    public Node getStart() {
        return super.getNode(Mth.floor(this.mob.getBoundingBox().minX), Mth.floor(this.mob.getBoundingBox().minY + 0.5), Mth.floor(this.mob.getBoundingBox().minZ));
    }
    
    @Override
    public Target getGoal(final double double1, final double double2, final double double3) {
        return new Target(super.getNode(Mth.floor(double1 - this.mob.getBbWidth() / 2.0f), Mth.floor(double2 + 0.5), Mth.floor(double3 - this.mob.getBbWidth() / 2.0f)));
    }
    
    @Override
    public int getNeighbors(final Node[] arr, final Node cqo) {
        int integer4 = 0;
        for (final Direction fp8 : Direction.values()) {
            final Node cqo2 = this.getWaterNode(cqo.x + fp8.getStepX(), cqo.y + fp8.getStepY(), cqo.z + fp8.getStepZ());
            if (cqo2 != null && !cqo2.closed) {
                arr[integer4++] = cqo2;
            }
        }
        return integer4;
    }
    
    @Override
    public BlockPathTypes getBlockPathType(final BlockGetter bjg, final int integer2, final int integer3, final int integer4, final Mob ala, final int integer6, final int integer7, final int integer8, final boolean boolean9, final boolean boolean10) {
        return this.getBlockPathType(bjg, integer2, integer3, integer4);
    }
    
    @Override
    public BlockPathTypes getBlockPathType(final BlockGetter bjg, final int integer2, final int integer3, final int integer4) {
        final BlockPos fk6 = new BlockPos(integer2, integer3, integer4);
        final FluidState coj7 = bjg.getFluidState(fk6);
        final BlockState byj8 = bjg.getBlockState(fk6);
        if (coj7.isEmpty() && byj8.isPathfindable(bjg, fk6.below(), PathComputationType.WATER) && byj8.isAir()) {
            return BlockPathTypes.BREACH;
        }
        if (!coj7.is(FluidTags.WATER) || !byj8.isPathfindable(bjg, fk6, PathComputationType.WATER)) {
            return BlockPathTypes.BLOCKED;
        }
        return BlockPathTypes.WATER;
    }
    
    @Nullable
    private Node getWaterNode(final int integer1, final int integer2, final int integer3) {
        final BlockPathTypes cqm5 = this.isFree(integer1, integer2, integer3);
        if ((this.allowBreaching && cqm5 == BlockPathTypes.BREACH) || cqm5 == BlockPathTypes.WATER) {
            return this.getNode(integer1, integer2, integer3);
        }
        return null;
    }
    
    @Nullable
    @Override
    protected Node getNode(final int integer1, final int integer2, final int integer3) {
        Node cqo5 = null;
        final BlockPathTypes cqm6 = this.getBlockPathType(this.mob.level, integer1, integer2, integer3);
        final float float7 = this.mob.getPathfindingMalus(cqm6);
        if (float7 >= 0.0f) {
            cqo5 = super.getNode(integer1, integer2, integer3);
            cqo5.type = cqm6;
            cqo5.costMalus = Math.max(cqo5.costMalus, float7);
            if (this.level.getFluidState(new BlockPos(integer1, integer2, integer3)).isEmpty()) {
                final Node node = cqo5;
                node.costMalus += 8.0f;
            }
        }
        if (cqm6 == BlockPathTypes.OPEN) {
            return cqo5;
        }
        return cqo5;
    }
    
    private BlockPathTypes isFree(final int integer1, final int integer2, final int integer3) {
        final BlockPos.MutableBlockPos a5 = new BlockPos.MutableBlockPos();
        for (int integer4 = integer1; integer4 < integer1 + this.entityWidth; ++integer4) {
            for (int integer5 = integer2; integer5 < integer2 + this.entityHeight; ++integer5) {
                for (int integer6 = integer3; integer6 < integer3 + this.entityDepth; ++integer6) {
                    final FluidState coj9 = this.level.getFluidState(a5.set(integer4, integer5, integer6));
                    final BlockState byj10 = this.level.getBlockState(a5.set(integer4, integer5, integer6));
                    if (coj9.isEmpty() && byj10.isPathfindable(this.level, a5.below(), PathComputationType.WATER) && byj10.isAir()) {
                        return BlockPathTypes.BREACH;
                    }
                    if (!coj9.is(FluidTags.WATER)) {
                        return BlockPathTypes.BLOCKED;
                    }
                }
            }
        }
        final BlockState byj11 = this.level.getBlockState(a5);
        if (byj11.isPathfindable(this.level, a5, PathComputationType.WATER)) {
            return BlockPathTypes.WATER;
        }
        return BlockPathTypes.BLOCKED;
    }
}
