package net.minecraft.world.level.block.state.predicate;

import java.util.Iterator;
import javax.annotation.Nullable;
import com.google.common.collect.Maps;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Map;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.BlockState;
import java.util.function.Predicate;

public class BlockStatePredicate implements Predicate<BlockState> {
    public static final Predicate<BlockState> ANY;
    private final StateDefinition<Block, BlockState> definition;
    private final Map<Property<?>, Predicate<Object>> properties;
    
    private BlockStatePredicate(final StateDefinition<Block, BlockState> cfk) {
        this.properties = Maps.newHashMap();
        this.definition = cfk;
    }
    
    public static BlockStatePredicate forBlock(final Block bvr) {
        return new BlockStatePredicate(bvr.getStateDefinition());
    }
    
    @Override
    public boolean test(@Nullable final BlockState cfj) {
        if (cfj == null || !cfj.getBlock().equals(this.definition.getOwner())) {
            return false;
        }
        if (this.properties.isEmpty()) {
            return true;
        }
        for (final Map.Entry<Property<?>, Predicate<Object>> entry4 : this.properties.entrySet()) {
            if (!this.applies(cfj, entry4.getKey(), entry4.getValue())) {
                return false;
            }
        }
        return true;
    }
    
    protected <T extends Comparable<T>> boolean applies(final BlockState cfj, final Property<T> cgl, final Predicate<Object> predicate) {
        final T comparable5 = cfj.<T>getValue(cgl);
        return predicate.test(comparable5);
    }
    
    public <V extends Comparable<V>> BlockStatePredicate where(final Property<V> cgl, final Predicate<Object> predicate) {
        if (!this.definition.getProperties().contains(cgl)) {
            throw new IllegalArgumentException(this.definition + " cannot support property " + cgl);
        }
        this.properties.put(cgl, predicate);
        return this;
    }
    
    static {
        ANY = (cfj -> true);
    }
}
