package net.minecraft.world.level;

import java.util.function.BiPredicate;
import java.util.Spliterator;
import java.util.stream.StreamSupport;
import java.util.stream.Stream;
import java.util.function.Predicate;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.entity.Entity;
import javax.annotation.Nullable;
import net.minecraft.world.level.border.WorldBorder;

public interface CollisionGetter extends BlockGetter {
    WorldBorder getWorldBorder();
    
    @Nullable
    BlockGetter getChunkForCollisions(final int integer1, final int integer2);
    
    default boolean isUnobstructed(@Nullable final Entity aom, final VoxelShape dfg) {
        return true;
    }
    
    default boolean isUnobstructed(final BlockState cfj, final BlockPos fu, final CollisionContext der) {
        final VoxelShape dfg5 = cfj.getCollisionShape(this, fu, der);
        return dfg5.isEmpty() || this.isUnobstructed(null, dfg5.move(fu.getX(), fu.getY(), fu.getZ()));
    }
    
    default boolean isUnobstructed(final Entity aom) {
        return this.isUnobstructed(aom, Shapes.create(aom.getBoundingBox()));
    }
    
    default boolean noCollision(final AABB deg) {
        return this.noCollision(null, deg, aom -> true);
    }
    
    default boolean noCollision(final Entity aom) {
        return this.noCollision(aom, aom.getBoundingBox(), aom -> true);
    }
    
    default boolean noCollision(final Entity aom, final AABB deg) {
        return this.noCollision(aom, deg, aom -> true);
    }
    
    default boolean noCollision(@Nullable final Entity aom, final AABB deg, final Predicate<Entity> predicate) {
        return this.getCollisions(aom, deg, predicate).allMatch(VoxelShape::isEmpty);
    }
    
    Stream<VoxelShape> getEntityCollisions(@Nullable final Entity aom, final AABB deg, final Predicate<Entity> predicate);
    
    default Stream<VoxelShape> getCollisions(@Nullable final Entity aom, final AABB deg, final Predicate<Entity> predicate) {
        return Stream.<VoxelShape>concat(this.getBlockCollisions(aom, deg), this.getEntityCollisions(aom, deg, predicate));
    }
    
    default Stream<VoxelShape> getBlockCollisions(@Nullable final Entity aom, final AABB deg) {
        return StreamSupport.<VoxelShape>stream((Spliterator<VoxelShape>)new CollisionSpliterator(this, aom, deg), false);
    }
    
    default Stream<VoxelShape> getBlockCollisions(@Nullable final Entity aom, final AABB deg, final BiPredicate<BlockState, BlockPos> biPredicate) {
        return StreamSupport.<VoxelShape>stream((Spliterator<VoxelShape>)new CollisionSpliterator(this, aom, deg, biPredicate), false);
    }
}
