package net.minecraft.world.level.storage.loot;

import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
import net.minecraft.world.level.storage.loot.predicates.LootItemConditions;
import java.util.function.Predicate;
import org.apache.logging.log4j.LogManager;
import java.util.Collections;
import java.util.Set;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.server.packs.resources.ResourceManager;
import com.google.gson.JsonElement;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableMap;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
import com.google.gson.Gson;
import org.apache.logging.log4j.Logger;
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;

public class PredicateManager extends SimpleJsonResourceReloadListener {
    private static final Logger LOGGER;
    private static final Gson GSON;
    private Map<ResourceLocation, LootItemCondition> conditions;
    
    public PredicateManager() {
        super(PredicateManager.GSON, "predicates");
        this.conditions = ImmutableMap.of();
    }
    
    @Nullable
    public LootItemCondition get(final ResourceLocation uh) {
        return this.conditions.get(uh);
    }
    
    @Override
    protected void apply(final Map<ResourceLocation, JsonElement> map, final ResourceManager abc, final ProfilerFiller ami) {
        final ImmutableMap.Builder<ResourceLocation, LootItemCondition> builder5 = ImmutableMap.<ResourceLocation, LootItemCondition>builder();
        LootItemCondition[] arr4;
        final ImmutableMap.Builder<ResourceLocation, CompositePredicate> builder6;
        LootItemCondition ddm2;
        map.forEach((uh, jsonElement) -> {
            try {
                if (jsonElement.isJsonArray()) {
                    arr4 = PredicateManager.GSON.<LootItemCondition[]>fromJson(jsonElement, LootItemCondition[].class);
                    builder6.put(uh, new CompositePredicate(arr4));
                }
                else {
                    ddm2 = PredicateManager.GSON.<LootItemCondition>fromJson(jsonElement, LootItemCondition.class);
                    builder6.put(uh, (CompositePredicate)ddm2);
                }
            }
            catch (Exception exception4) {
                PredicateManager.LOGGER.error("Couldn't parse loot table {}", uh, exception4);
            }
            return;
        });
        final Map<ResourceLocation, LootItemCondition> map2 = builder5.build();
        final ValidationContext dbe7 = new ValidationContext(LootContextParamSets.ALL_PARAMS, map2::get, uh -> null);
        map2.forEach((uh, ddm) -> ddm.validate(dbe7.enterCondition("{" + uh + "}", uh)));
        dbe7.getProblems().forEach((string1, string2) -> PredicateManager.LOGGER.warn("Found validation problem in " + string1 + ": " + string2));
        this.conditions = map2;
    }
    
    public Set<ResourceLocation> getKeys() {
        return Collections.<ResourceLocation>unmodifiableSet(this.conditions.keySet());
    }
    
    static {
        LOGGER = LogManager.getLogger();
        GSON = Deserializers.createConditionSerializer().create();
    }
    
    static class CompositePredicate implements LootItemCondition {
        private final LootItemCondition[] terms;
        private final Predicate<LootContext> composedPredicate;
        
        private CompositePredicate(final LootItemCondition[] arr) {
            this.terms = arr;
            this.composedPredicate = LootItemConditions.<LootContext>andConditions(arr);
        }
        
        @Override
        public final boolean test(final LootContext dat) {
            return this.composedPredicate.test(dat);
        }
        
        @Override
        public void validate(final ValidationContext dbe) {
            super.validate(dbe);
            for (int integer3 = 0; integer3 < this.terms.length; ++integer3) {
                this.terms[integer3].validate(dbe.forChild(".term[" + integer3 + "]"));
            }
        }
        
        @Override
        public LootItemConditionType getType() {
            throw new UnsupportedOperationException();
        }
    }
}
