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> byk) {
        this.properties = Maps.newHashMap();
        this.definition = byk;
    }
    
    public static BlockStatePredicate forBlock(final Block bph) {
        return new BlockStatePredicate(bph.getStateDefinition());
    }
    
    @Override
    public boolean test(@Nullable final BlockState byj) {
        if (byj == null || !byj.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(byj, entry4.getKey(), entry4.getValue())) {
                return false;
            }
        }
        return true;
    }
    
    protected <T extends Comparable<T>> boolean applies(final BlockState byj, final Property<T> bzm, final Predicate<Object> predicate) {
        final T comparable5 = byj.<T>getValue(bzm);
        return predicate.test(comparable5);
    }
    
    public <V extends Comparable<V>> BlockStatePredicate where(final Property<V> bzm, final Predicate<Object> predicate) {
        if (!this.definition.getProperties().contains(bzm)) {
            throw new IllegalArgumentException(this.definition + " cannot support property " + bzm);
        }
        this.properties.put(bzm, predicate);
        return this;
    }
    
    static {
        ANY = (byj -> true);
    }
}
