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

import javax.annotation.Nullable;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.HashMultimap;
import java.util.Set;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.resources.ResourceLocation;
import java.util.function.Function;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet;
import java.util.function.Supplier;
import com.google.common.collect.Multimap;

public class ValidationContext {
    private final Multimap<String, String> problems;
    private final Supplier<String> context;
    private final LootContextParamSet params;
    private final Function<ResourceLocation, LootItemCondition> conditionResolver;
    private final Set<ResourceLocation> visitedConditions;
    private final Function<ResourceLocation, LootTable> tableResolver;
    private final Set<ResourceLocation> visitedTables;
    private String contextCache;
    
    public ValidationContext(final LootContextParamSet cty, final Function<ResourceLocation, LootItemCondition> function2, final Function<ResourceLocation, LootTable> function3) {
        this(HashMultimap.create(), () -> "", cty, function2, ImmutableSet.of(), function3, ImmutableSet.of());
    }
    
    public ValidationContext(final Multimap<String, String> multimap, final Supplier<String> supplier, final LootContextParamSet cty, final Function<ResourceLocation, LootItemCondition> function4, final Set<ResourceLocation> set5, final Function<ResourceLocation, LootTable> function6, final Set<ResourceLocation> set7) {
        this.problems = multimap;
        this.context = supplier;
        this.params = cty;
        this.conditionResolver = function4;
        this.visitedConditions = set5;
        this.tableResolver = function6;
        this.visitedTables = set7;
    }
    
    private String getContext() {
        if (this.contextCache == null) {
            this.contextCache = this.context.get();
        }
        return this.contextCache;
    }
    
    public void reportProblem(final String string) {
        this.problems.put(this.getContext(), string);
    }
    
    public ValidationContext forChild(final String string) {
        return new ValidationContext(this.problems, () -> this.getContext() + string, this.params, this.conditionResolver, this.visitedConditions, this.tableResolver, this.visitedTables);
    }
    
    public ValidationContext enterTable(final String string, final ResourceLocation sm) {
        final ImmutableSet<ResourceLocation> immutableSet4 = ImmutableSet.<ResourceLocation>builder().addAll(this.visitedTables).add(sm).build();
        return new ValidationContext(this.problems, () -> this.getContext() + string, this.params, this.conditionResolver, this.visitedConditions, this.tableResolver, immutableSet4);
    }
    
    public ValidationContext enterCondition(final String string, final ResourceLocation sm) {
        final ImmutableSet<ResourceLocation> immutableSet4 = ImmutableSet.<ResourceLocation>builder().addAll(this.visitedConditions).add(sm).build();
        return new ValidationContext(this.problems, () -> this.getContext() + string, this.params, this.conditionResolver, immutableSet4, this.tableResolver, this.visitedTables);
    }
    
    public boolean hasVisitedTable(final ResourceLocation sm) {
        return this.visitedTables.contains(sm);
    }
    
    public boolean hasVisitedCondition(final ResourceLocation sm) {
        return this.visitedConditions.contains(sm);
    }
    
    public Multimap<String, String> getProblems() {
        return ImmutableMultimap.copyOf(this.problems);
    }
    
    public void validateUser(final LootContextUser cry) {
        this.params.validateUser(this, cry);
    }
    
    @Nullable
    public LootTable resolveLootTable(final ResourceLocation sm) {
        return this.tableResolver.apply(sm);
    }
    
    @Nullable
    public LootItemCondition resolveCondition(final ResourceLocation sm) {
        return this.conditionResolver.apply(sm);
    }
    
    public ValidationContext setParams(final LootContextParamSet cty) {
        return new ValidationContext(this.problems, this.context, cty, this.conditionResolver, this.visitedConditions, this.tableResolver, this.visitedTables);
    }
}
