package net.minecraft.world.level;

import java.util.function.Predicate;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.Vec3;

public class ClipContext {
    private final Vec3 from;
    private final Vec3 to;
    private final Block block;
    private final Fluid fluid;
    private final CollisionContext collisionContext;
    
    public ClipContext(final Vec3 cvl1, final Vec3 cvl2, final Block a, final Fluid b, final Entity akq) {
        this.from = cvl1;
        this.to = cvl2;
        this.block = a;
        this.fluid = b;
        this.collisionContext = CollisionContext.of(akq);
    }
    
    public Vec3 getTo() {
        return this.to;
    }
    
    public Vec3 getFrom() {
        return this.from;
    }
    
    public VoxelShape getBlockShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return this.block.get(byj, bjg, fk, this.collisionContext);
    }
    
    public VoxelShape getFluidShape(final FluidState coj, final BlockGetter bjg, final BlockPos fk) {
        return this.fluid.canPick(coj) ? coj.getShape(bjg, fk) : Shapes.empty();
    }
    
    public enum Block implements ShapeGetter {
        COLLIDER(BlockState::getCollisionShape), 
        OUTLINE(BlockState::getShape);
        
        private final ShapeGetter shapeGetter;
        
        private Block(final ShapeGetter c) {
            this.shapeGetter = c;
        }
        
        @Override
        public VoxelShape get(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
            return this.shapeGetter.get(byj, bjg, fk, cvq);
        }
    }
    
    public enum Fluid {
        NONE(coj -> false), 
        SOURCE_ONLY(FluidState::isSource), 
        ANY(coj -> !coj.isEmpty());
        
        private final Predicate<FluidState> canPick;
        
        private Fluid(final Predicate<FluidState> predicate) {
            this.canPick = predicate;
        }
        
        public boolean canPick(final FluidState coj) {
            return this.canPick.test(coj);
        }
    }
    
    public interface ShapeGetter {
        VoxelShape get(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq);
    }
}
