package net.minecraft.advancements;

import com.google.common.collect.Lists;
import javax.annotation.Nullable;
import java.util.List;
import com.google.gson.JsonParseException;
import net.minecraft.util.GsonHelper;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonNull;
import com.google.gson.JsonElement;
import java.util.Arrays;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.item.ItemEntity;
import java.util.Iterator;
import net.minecraft.world.entity.player.Player;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.commands.CommandFunction;
import net.minecraft.resources.ResourceLocation;

public class AdvancementRewards {
    public static final AdvancementRewards EMPTY;
    private final int experience;
    private final ResourceLocation[] loot;
    private final ResourceLocation[] recipes;
    private final CommandFunction.CacheableFunction function;
    
    public AdvancementRewards(final int integer, final ResourceLocation[] arr2, final ResourceLocation[] arr3, final CommandFunction.CacheableFunction a) {
        this.experience = integer;
        this.loot = arr2;
        this.recipes = arr3;
        this.function = a;
    }
    
    public void grant(final ServerPlayer ze) {
        ze.giveExperiencePoints(this.experience);
        final LootContext dat3 = new LootContext.Builder(ze.getLevel()).<Entity>withParameter(LootContextParams.THIS_ENTITY, ze).<BlockPos>withParameter(LootContextParams.BLOCK_POS, ze.blockPosition()).withRandom(ze.getRandom()).create(LootContextParamSets.ADVANCEMENT_REWARD);
        boolean boolean4 = false;
        for (final ResourceLocation uh8 : this.loot) {
            for (final ItemStack bki10 : ze.server.getLootTables().get(uh8).getRandomItems(dat3)) {
                if (ze.addItem(bki10)) {
                    ze.level.playSound(null, ze.getX(), ze.getY(), ze.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2f, ((ze.getRandom().nextFloat() - ze.getRandom().nextFloat()) * 0.7f + 1.0f) * 2.0f);
                    boolean4 = true;
                }
                else {
                    final ItemEntity bbg11 = ze.drop(bki10, false);
                    if (bbg11 == null) {
                        continue;
                    }
                    bbg11.setNoPickUpDelay();
                    bbg11.setOwner(ze.getUUID());
                }
            }
        }
        if (boolean4) {
            ze.inventoryMenu.broadcastChanges();
        }
        if (this.recipes.length > 0) {
            ze.awardRecipesByKey(this.recipes);
        }
        final MinecraftServer minecraftServer5 = ze.server;
        this.function.get(minecraftServer5.getFunctions()).ifPresent(cw -> minecraftServer5.getFunctions().execute(cw, ze.createCommandSourceStack().withSuppressedOutput().withPermission(2)));
    }
    
    @Override
    public String toString() {
        return "AdvancementRewards{experience=" + this.experience + ", loot=" + Arrays.toString(this.loot) + ", recipes=" + Arrays.toString(this.recipes) + ", function=" + this.function + '}';
    }
    
    public JsonElement serializeToJson() {
        if (this == AdvancementRewards.EMPTY) {
            return JsonNull.INSTANCE;
        }
        final JsonObject jsonObject2 = new JsonObject();
        if (this.experience != 0) {
            jsonObject2.addProperty("experience", this.experience);
        }
        if (this.loot.length > 0) {
            final JsonArray jsonArray3 = new JsonArray();
            for (final ResourceLocation uh7 : this.loot) {
                jsonArray3.add(uh7.toString());
            }
            jsonObject2.add("loot", jsonArray3);
        }
        if (this.recipes.length > 0) {
            final JsonArray jsonArray3 = new JsonArray();
            for (final ResourceLocation uh7 : this.recipes) {
                jsonArray3.add(uh7.toString());
            }
            jsonObject2.add("recipes", jsonArray3);
        }
        if (this.function.getId() != null) {
            jsonObject2.addProperty("function", this.function.getId().toString());
        }
        return jsonObject2;
    }
    
    public static AdvancementRewards deserialize(final JsonObject jsonObject) throws JsonParseException {
        final int integer2 = GsonHelper.getAsInt(jsonObject, "experience", 0);
        final JsonArray jsonArray3 = GsonHelper.getAsJsonArray(jsonObject, "loot", new JsonArray());
        final ResourceLocation[] arr4 = new ResourceLocation[jsonArray3.size()];
        for (int integer3 = 0; integer3 < arr4.length; ++integer3) {
            arr4[integer3] = new ResourceLocation(GsonHelper.convertToString(jsonArray3.get(integer3), "loot[" + integer3 + "]"));
        }
        final JsonArray jsonArray4 = GsonHelper.getAsJsonArray(jsonObject, "recipes", new JsonArray());
        final ResourceLocation[] arr5 = new ResourceLocation[jsonArray4.size()];
        for (int integer4 = 0; integer4 < arr5.length; ++integer4) {
            arr5[integer4] = new ResourceLocation(GsonHelper.convertToString(jsonArray4.get(integer4), "recipes[" + integer4 + "]"));
        }
        CommandFunction.CacheableFunction a7;
        if (jsonObject.has("function")) {
            a7 = new CommandFunction.CacheableFunction(new ResourceLocation(GsonHelper.getAsString(jsonObject, "function")));
        }
        else {
            a7 = CommandFunction.CacheableFunction.NONE;
        }
        return new AdvancementRewards(integer2, arr4, arr5, a7);
    }
    
    static {
        EMPTY = new AdvancementRewards(0, new ResourceLocation[0], new ResourceLocation[0], CommandFunction.CacheableFunction.NONE);
    }
    
    public static class Builder {
        private int experience;
        private final List<ResourceLocation> loot;
        private final List<ResourceLocation> recipes;
        @Nullable
        private ResourceLocation function;
        
        public Builder() {
            this.loot = Lists.newArrayList();
            this.recipes = Lists.newArrayList();
        }
        
        public static Builder experience(final int integer) {
            return new Builder().addExperience(integer);
        }
        
        public Builder addExperience(final int integer) {
            this.experience += integer;
            return this;
        }
        
        public static Builder recipe(final ResourceLocation uh) {
            return new Builder().addRecipe(uh);
        }
        
        public Builder addRecipe(final ResourceLocation uh) {
            this.recipes.add(uh);
            return this;
        }
        
        public AdvancementRewards build() {
            return new AdvancementRewards(this.experience, this.loot.<ResourceLocation>toArray(new ResourceLocation[0]), this.recipes.<ResourceLocation>toArray(new ResourceLocation[0]), (this.function == null) ? CommandFunction.CacheableFunction.NONE : new CommandFunction.CacheableFunction(this.function));
        }
    }
}
